From 0ebb4f54f2ea63fc14187532f2e96346a8b333b4 Mon Sep 17 00:00:00 2001 From: vados-dev Date: Mon, 2 Mar 2026 21:58:50 +0300 Subject: [PATCH 1/1] mikro_bak Initial Commit --- .gitignore | 2 + .../20260220/20260220092832-Binary.backup | Bin 0 -> 288928 bytes .../20260220/20260220092832-Config.rsc | 3956 ++++++++++++++++ .../20260220/20260220110005-Binary.backup | Bin 0 -> 288924 bytes .../20260220/20260220110005-Config.rsc | 3954 ++++++++++++++++ .../20260220/20260220110205-Binary.backup | Bin 0 -> 288926 bytes .../20260220/20260220110205-Config.rsc | 3955 ++++++++++++++++ .../20260220/20260220110853-Binary.backup | Bin 0 -> 288928 bytes .../20260220/20260220110853-Config.rsc | 3956 ++++++++++++++++ .../20260220/20260220111036-Binary.backup | Bin 0 -> 288926 bytes .../20260220/20260220111036-Config.rsc | 3955 ++++++++++++++++ .../20260220/20260220142012-Binary.backup | Bin 0 -> 288926 bytes .../20260220/20260220142012-Config.rsc | 3955 ++++++++++++++++ .../20260220/20260220190012-Binary.backup | Bin 0 -> 288926 bytes .../20260220/20260220190012-Config.rsc | 3956 ++++++++++++++++ .../20260220/20260220210012-Binary.backup | Bin 0 -> 288912 bytes .../20260220/20260220210012-Config.rsc | 3955 ++++++++++++++++ .../20260221/20260221130011-Binary.backup | Bin 0 -> 288912 bytes .../20260221/20260221130011-Config.rsc | 3955 ++++++++++++++++ .../20260224/20260224050012-Binary.backup | Bin 0 -> 289014 bytes .../20260224/20260224050012-Config.rsc | 3956 ++++++++++++++++ .../20260225/20260225004202-Binary.backup | Bin 0 -> 289014 bytes .../20260225/20260225004202-Config.rsc | 3956 ++++++++++++++++ .../20260225/20260225012726-Binary.backup | Bin 0 -> 289014 bytes .../20260225/20260225012726-Config.rsc | 3956 ++++++++++++++++ .../20260225/20260225120026-Binary.backup | Bin 0 -> 289014 bytes .../20260225/20260225120026-Config.rsc | 3957 ++++++++++++++++ .../20260225/20260225150026-Binary.backup | Bin 0 -> 289184 bytes .../20260225/20260225150026-Config.rsc | 3959 ++++++++++++++++ .../20260226/20260226084004-Binary.backup | Bin 0 -> 289184 bytes .../20260226/20260226084004-Config.rsc | 3959 ++++++++++++++++ .../20260226/20260226092005-Binary.backup | Bin 0 -> 289184 bytes .../20260226/20260226092005-Config.rsc | 3959 ++++++++++++++++ .../20260226/20260226220005-Binary.backup | Bin 0 -> 289184 bytes .../20260226/20260226220005-Config.rsc | 3958 ++++++++++++++++ .../20260227/20260227150358-Binary.backup | Bin 0 -> 289184 bytes .../20260227/20260227154850-Binary.backup | Bin 0 -> 289184 bytes .../20260227/20260227154850-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228043319-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228044004-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228044733-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228050004-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228050259-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228050259-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228051202-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228051202-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228051337-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228051337-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228051612-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228051612-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228051903-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228051903-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228052004-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228052004-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228055323-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228055323-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228060004-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228060004-Config.rsc | 3958 ++++++++++++++++ .../20260228/20260228062004-Binary.backup | Bin 0 -> 289184 bytes .../20260228/20260228062004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302143118-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302143118-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302144005-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302144005-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302150004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302150004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302152005-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302152005-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302154004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302154004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302160004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302160004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302162004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302162004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302164004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302164004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302170004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302170004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302172004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302172004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302174004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302174004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302180004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302180004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302182004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302182004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302184004-Binary.backup | Bin 0 -> 289184 bytes .../20260302/20260302184004-Config.rsc | 3958 ++++++++++++++++ .../20260302/20260302190003-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302190003-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302192004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302192004-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302194004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302194004-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302200004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302200004-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302202004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302202004-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302204004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302204004-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302210004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302210004-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302212004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302212004-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302212918-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302212918-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302214004-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302214004-Config.rsc | 3971 +++++++++++++++++ .../20260220/20260220092832-Diff-Config.rsc | 0 .../20260220/20260220110005-Diff-Config.rsc | 8 + .../20260220/20260220110205-Diff-Config.rsc | 7 + .../20260220/20260220110853-Diff-Config.rsc | 2 + .../20260220/20260220111036-Diff-Config.rsc | 2 + .../20260220/20260220142012-Diff-Config.rsc | 8 + .../20260220/20260220190012-Diff-Config.rsc | 7 + .../20260220/20260220210012-Diff-Config.rsc | 7 + .../20260221/20260221130011-Diff-Config.rsc | 8 + .../20260224/20260224050012-Diff-Config.rsc | 2 + .../20260225/20260225004202-Diff-Config.rsc | 8 + .../20260225/20260225012726-Diff-Config.rsc | 8 + .../20260225/20260225120026-Diff-Config.rsc | 7 + .../20260225/20260225150026-Diff-Config.rsc | 3 + .../20260226/20260226084004-Diff-Config.rsc | 8 + .../20260226/20260226092005-Diff-Config.rsc | 8 + .../20260226/20260226220005-Diff-Config.rsc | 7 + .../20260227/20260227150358-Diff-Config.rsc | 0 .../20260227/20260227154850-Diff-Config.rsc | 0 .../20260228/20260228043319-Diff-Config.rsc | 4 + .../20260228/20260228044004-Diff-Config.rsc | 4 + .../20260228/20260228044733-Diff-Config.rsc | 4 + .../20260228/20260228050004-Diff-Config.rsc | 4 + .../20260228/20260228050259-Diff-Config.rsc | 4 + .../20260228/20260228051202-Diff-Config.rsc | 4 + .../20260228/20260228051337-Diff-Config.rsc | 4 + .../20260228/20260228051612-Diff-Config.rsc | 4 + .../20260228/20260228051903-Diff-Config.rsc | 4 + .../20260228/20260228052004-Diff-Config.rsc | 4 + .../20260228/20260228055323-Diff-Config.rsc | 4 + .../20260228/20260228060004-Diff-Config.rsc | 4 + .../20260228/20260228062004-Diff-Config.rsc | 4 + .../20260302/20260302143118-Diff-Config.rsc | 12 + .../20260302/20260302144005-Diff-Config.rsc | 4 + .../20260302/20260302150004-Diff-Config.rsc | 4 + .../20260302/20260302152005-Diff-Config.rsc | 4 + .../20260302/20260302154004-Diff-Config.rsc | 4 + .../20260302/20260302160004-Diff-Config.rsc | 4 + .../20260302/20260302162004-Diff-Config.rsc | 4 + .../20260302/20260302164004-Diff-Config.rsc | 4 + .../20260302/20260302170004-Diff-Config.rsc | 4 + .../20260302/20260302172004-Diff-Config.rsc | 4 + .../20260302/20260302174004-Diff-Config.rsc | 4 + .../20260302/20260302180004-Diff-Config.rsc | 4 + .../20260302/20260302182004-Diff-Config.rsc | 4 + .../20260302/20260302184004-Diff-Config.rsc | 4 + .../20260302/20260302190003-Diff-Config.rsc | 52 + .../20260302/20260302192004-Diff-Config.rsc | 4 + .../20260302/20260302194004-Diff-Config.rsc | 4 + .../20260302/20260302200004-Diff-Config.rsc | 4 + .../20260302/20260302202004-Diff-Config.rsc | 4 + .../20260302/20260302204004-Diff-Config.rsc | 4 + .../20260302/20260302210004-Diff-Config.rsc | 4 + .../20260302/20260302212004-Diff-Config.rsc | 4 + .../20260302/20260302212918-Diff-Config.rsc | 4 + .../20260302/20260302214004-Diff-Config.rsc | 4 + .../20260220/20260220072118-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220072118-Config.rsc | 2684 +++++++++++ .../20260220/20260220072834-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220072834-Config.rsc | 2684 +++++++++++ .../20260220/20260220072919-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220072919-Config.rsc | 2684 +++++++++++ .../20260220/20260220083844-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220083844-Config.rsc | 2684 +++++++++++ .../20260220/20260220083924-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220083924-Config.rsc | 2684 +++++++++++ .../20260220/20260220085626-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220085626-Config.rsc | 2684 +++++++++++ .../20260220/20260220085921-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220085921-Config.rsc | 2684 +++++++++++ .../20260220/20260220085933-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220085933-Config.rsc | 2684 +++++++++++ .../20260220/20260220090536-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220090536-Config.rsc | 2684 +++++++++++ .../20260220/20260220090557-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220090557-Config.rsc | 2684 +++++++++++ .../20260220/20260220103113-Binary.backup | Bin 0 -> 300264 bytes MikroNUC/20260220/20260220103113-Config.rsc | 2686 +++++++++++ .../20260220/20260220103550-Binary.backup | Bin 0 -> 300266 bytes MikroNUC/20260220/20260220103550-Config.rsc | 2687 +++++++++++ .../20260220/20260220130018-Binary.backup | Bin 0 -> 297833 bytes MikroNUC/20260220/20260220130018-Config.rsc | 2681 +++++++++++ .../20260220/20260220132007-Binary.backup | Bin 0 -> 298179 bytes MikroNUC/20260220/20260220132007-Config.rsc | 2680 +++++++++++ .../20260220/20260220134006-Binary.backup | Bin 0 -> 299469 bytes MikroNUC/20260220/20260220134006-Config.rsc | 2697 +++++++++++ .../20260220/20260220140006-Binary.backup | Bin 0 -> 299463 bytes MikroNUC/20260220/20260220140006-Config.rsc | 2697 +++++++++++ .../20260220/20260220192007-Binary.backup | Bin 0 -> 300426 bytes MikroNUC/20260220/20260220192007-Config.rsc | 2718 +++++++++++ .../20260220/20260220212007-Binary.backup | Bin 0 -> 300524 bytes MikroNUC/20260220/20260220212007-Config.rsc | 2720 +++++++++++ .../20260220/20260220214006-Binary.backup | Bin 0 -> 301270 bytes MikroNUC/20260220/20260220214006-Config.rsc | 2730 +++++++++++ .../20260220/20260220220007-Binary.backup | Bin 0 -> 302374 bytes MikroNUC/20260220/20260220220007-Config.rsc | 2742 ++++++++++++ .../20260221/20260221232006-Binary.backup | Bin 0 -> 302376 bytes MikroNUC/20260221/20260221232006-Config.rsc | 2742 ++++++++++++ .../20260222/20260222002006-Binary.backup | Bin 0 -> 302656 bytes MikroNUC/20260222/20260222002006-Config.rsc | 2746 ++++++++++++ .../20260222/20260222004007-Binary.backup | Bin 0 -> 303255 bytes MikroNUC/20260222/20260222004007-Config.rsc | 2753 ++++++++++++ .../20260222/20260222010006-Binary.backup | Bin 0 -> 303527 bytes MikroNUC/20260222/20260222010006-Config.rsc | 2757 ++++++++++++ .../20260222/20260222012007-Binary.backup | Bin 0 -> 305075 bytes MikroNUC/20260222/20260222012007-Config.rsc | 2754 ++++++++++++ .../20260222/20260222014006-Binary.backup | Bin 0 -> 302761 bytes MikroNUC/20260222/20260222014006-Config.rsc | 2746 ++++++++++++ .../20260224/20260224122252-Binary.backup | Bin 0 -> 302763 bytes MikroNUC/20260224/20260224122252-Config.rsc | 2747 ++++++++++++ .../20260224/20260224122441-Binary.backup | Bin 0 -> 302761 bytes MikroNUC/20260224/20260224122441-Config.rsc | 2746 ++++++++++++ .../20260224/20260224122638-Binary.backup | Bin 0 -> 302763 bytes MikroNUC/20260224/20260224122638-Config.rsc | 2747 ++++++++++++ .../20260224/20260224192006-Binary.backup | Bin 0 -> 302860 bytes MikroNUC/20260224/20260224192006-Config.rsc | 2747 ++++++++++++ .../20260224/20260224194007-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224194007-Config.rsc | 2747 ++++++++++++ .../20260224/20260224214007-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224214007-Config.rsc | 2748 ++++++++++++ .../20260224/20260224215052-Binary.backup | Bin 0 -> 307414 bytes MikroNUC/20260224/20260224215052-Config.rsc | 2747 ++++++++++++ .../20260224/20260224215237-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224215237-Config.rsc | 2748 ++++++++++++ .../20260224/20260224215620-Binary.backup | Bin 0 -> 307414 bytes MikroNUC/20260224/20260224215620-Config.rsc | 2747 ++++++++++++ .../20260224/20260224220006-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224220006-Config.rsc | 2748 ++++++++++++ .../20260224/20260224220134-Binary.backup | Bin 0 -> 307418 bytes MikroNUC/20260224/20260224220134-Config.rsc | 2749 ++++++++++++ .../20260224/20260224223439-Binary.backup | Bin 0 -> 307414 bytes MikroNUC/20260224/20260224223439-Config.rsc | 2747 ++++++++++++ .../20260224/20260224230007-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224230007-Config.rsc | 2748 ++++++++++++ .../20260224/20260224230243-Binary.backup | Bin 0 -> 307414 bytes MikroNUC/20260224/20260224230243-Config.rsc | 2747 ++++++++++++ .../20260224/20260224230525-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224230525-Config.rsc | 2748 ++++++++++++ .../20260224/20260224230855-Binary.backup | Bin 0 -> 307414 bytes MikroNUC/20260224/20260224230855-Config.rsc | 2747 ++++++++++++ .../20260224/20260224231054-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224231054-Config.rsc | 2748 ++++++++++++ .../20260224/20260224231651-Binary.backup | Bin 0 -> 307414 bytes MikroNUC/20260224/20260224231651-Config.rsc | 2747 ++++++++++++ .../20260224/20260224231900-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224231900-Config.rsc | 2748 ++++++++++++ .../20260224/20260224232005-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260224/20260224232005-Config.rsc | 2748 ++++++++++++ MikroNUC/20260227/20260227162307-Config.rsc | 2747 ++++++++++++ MikroNUC/20260228/20260228043316-Config.rsc | 2747 ++++++++++++ MikroNUC/20260228/20260228044001-Config.rsc | 2747 ++++++++++++ .../20260228/20260228044730-Binary.backup | Bin 0 -> 307416 bytes .../20260228/20260228050001-Binary.backup | Bin 0 -> 307416 bytes .../20260228/20260228050256-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228050256-Config.rsc | 2748 ++++++++++++ .../20260228/20260228051159-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228051159-Config.rsc | 2748 ++++++++++++ .../20260228/20260228051334-Binary.backup | Bin 0 -> 307414 bytes MikroNUC/20260228/20260228051334-Config.rsc | 2747 ++++++++++++ .../20260228/20260228051609-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228051609-Config.rsc | 2748 ++++++++++++ .../20260228/20260228051900-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228051900-Config.rsc | 2748 ++++++++++++ .../20260228/20260228052001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228052001-Config.rsc | 2748 ++++++++++++ .../20260228/20260228055320-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228055320-Config.rsc | 2748 ++++++++++++ .../20260228/20260228060001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228060001-Config.rsc | 2748 ++++++++++++ .../20260228/20260228062001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260228/20260228062001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302143114-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302143114-Config.rsc | 2748 ++++++++++++ .../20260302/20260302144001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302144001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302150001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302150001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302152002-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302152002-Config.rsc | 2748 ++++++++++++ .../20260302/20260302154001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302154001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302160001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302160001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302162001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302162001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302164001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302164001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302170001-Binary.backup | Bin 0 -> 307416 bytes MikroNUC/20260302/20260302170001-Config.rsc | 2748 ++++++++++++ .../20260302/20260302172001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302172001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302174001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302174001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302180001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302180001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302182001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302182001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302184001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302184001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302190001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302190001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302192001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302192001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302194001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302194001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302200001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302200001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302202001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302202001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302204001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302204001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302210001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302210001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302212001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302212001-Config.rsc | 2770 ++++++++++++ .../20260302/20260302212913-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302212913-Config.rsc | 2770 ++++++++++++ .../20260302/20260302214002-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302214002-Config.rsc | 2770 ++++++++++++ .../20260220/20260220072118-Diff-Config.rsc | 0 .../20260220/20260220072834-Diff-Config.rsc | 0 .../20260220/20260220072919-Diff-Config.rsc | 0 .../20260220/20260220083844-Diff-Config.rsc | 0 .../20260220/20260220083924-Diff-Config.rsc | 0 .../20260220/20260220085626-Diff-Config.rsc | 0 .../20260220/20260220085921-Diff-Config.rsc | 0 .../20260220/20260220085933-Diff-Config.rsc | 0 .../20260220/20260220090536-Diff-Config.rsc | 0 .../20260220/20260220090557-Diff-Config.rsc | 0 .../20260220/20260220103113-Diff-Config.rsc | 3 + .../20260220/20260220103550-Diff-Config.rsc | 2 + .../20260220/20260220130018-Diff-Config.rsc | 28 + .../20260220/20260220132007-Diff-Config.rsc | 23 + .../20260220/20260220134006-Diff-Config.rsc | 27 + .../20260220/20260220140006-Diff-Config.rsc | 4 + .../20260220/20260220192007-Diff-Config.rsc | 23 + .../20260220/20260220212007-Diff-Config.rsc | 3 + .../20260220/20260220214006-Diff-Config.rsc | 44 + .../20260220/20260220220007-Diff-Config.rsc | 26 + .../20260221/20260221232006-Diff-Config.rsc | 6 + .../20260222/20260222002006-Diff-Config.rsc | 5 + .../20260222/20260222004007-Diff-Config.rsc | 8 + .../20260222/20260222010006-Diff-Config.rsc | 28 + .../20260222/20260222012007-Diff-Config.rsc | 31 + .../20260222/20260222014006-Diff-Config.rsc | 9 + .../20260224/20260224122252-Diff-Config.rsc | 9 + .../20260224/20260224122441-Diff-Config.rsc | 9 + .../20260224/20260224122638-Diff-Config.rsc | 2 + .../20260224/20260224192006-Diff-Config.rsc | 11 + .../20260224/20260224194007-Diff-Config.rsc | 4 + .../20260224/20260224214007-Diff-Config.rsc | 5 + .../20260224/20260224215052-Diff-Config.rsc | 2 + .../20260224/20260224215237-Diff-Config.rsc | 2 + .../20260224/20260224215620-Diff-Config.rsc | 2 + .../20260224/20260224220006-Diff-Config.rsc | 2 + .../20260224/20260224220134-Diff-Config.rsc | 2 + .../20260224/20260224223439-Diff-Config.rsc | 4 + .../20260224/20260224230007-Diff-Config.rsc | 2 + .../20260224/20260224230243-Diff-Config.rsc | 2 + .../20260224/20260224230525-Diff-Config.rsc | 2 + .../20260224/20260224230855-Diff-Config.rsc | 2 + .../20260224/20260224231054-Diff-Config.rsc | 2 + .../20260224/20260224231651-Diff-Config.rsc | 2 + .../20260224/20260224231900-Diff-Config.rsc | 2 + .../20260228/20260228043316-Diff-Config.rsc | 4 + .../20260228/20260228044001-Diff-Config.rsc | 4 + .../20260228/20260228044730-Diff-Config.rsc | 6 + .../20260228/20260228050001-Diff-Config.rsc | 4 + .../20260228/20260228050256-Diff-Config.rsc | 4 + .../20260228/20260228051159-Diff-Config.rsc | 4 + .../20260228/20260228051334-Diff-Config.rsc | 6 + .../20260228/20260228051609-Diff-Config.rsc | 6 + .../20260228/20260228051900-Diff-Config.rsc | 4 + .../20260228/20260228052001-Diff-Config.rsc | 4 + .../20260228/20260228055320-Diff-Config.rsc | 4 + .../20260228/20260228060001-Diff-Config.rsc | 4 + .../20260228/20260228062001-Diff-Config.rsc | 4 + .../20260302/20260302143114-Diff-Config.rsc | 4 + .../20260302/20260302144001-Diff-Config.rsc | 4 + .../20260302/20260302150001-Diff-Config.rsc | 4 + .../20260302/20260302152002-Diff-Config.rsc | 4 + .../20260302/20260302154001-Diff-Config.rsc | 4 + .../20260302/20260302160001-Diff-Config.rsc | 4 + .../20260302/20260302162001-Diff-Config.rsc | 4 + .../20260302/20260302164001-Diff-Config.rsc | 4 + .../20260302/20260302170001-Diff-Config.rsc | 4 + .../20260302/20260302172001-Diff-Config.rsc | 244 + .../20260302/20260302174001-Diff-Config.rsc | 4 + .../20260302/20260302180001-Diff-Config.rsc | 4 + .../20260302/20260302182001-Diff-Config.rsc | 4 + .../20260302/20260302184001-Diff-Config.rsc | 4 + .../20260302/20260302190001-Diff-Config.rsc | 4 + .../20260302/20260302192001-Diff-Config.rsc | 4 + .../20260302/20260302194001-Diff-Config.rsc | 4 + .../20260302/20260302200001-Diff-Config.rsc | 4 + .../20260302/20260302202001-Diff-Config.rsc | 4 + .../20260302/20260302204001-Diff-Config.rsc | 4 + .../20260302/20260302210001-Diff-Config.rsc | 4 + .../20260302/20260302212001-Diff-Config.rsc | 4 + .../20260302/20260302212913-Diff-Config.rsc | 4 + .../20260302/20260302214002-Diff-Config.rsc | 4 + .../20260220/20260220102624-Binary.backup | Bin 0 -> 163806 bytes .../20260220/20260220102624-Config.rsc | 3412 ++++++++++++++ .../20260220/20260220103508-Binary.backup | Bin 0 -> 164118 bytes .../20260220/20260220103508-Config.rsc | 3418 ++++++++++++++ .../20260220/20260220144020-Binary.backup | Bin 0 -> 164118 bytes .../20260220/20260220144020-Config.rsc | 3418 ++++++++++++++ .../20260220/20260220204047-Binary.backup | Bin 0 -> 164118 bytes .../20260220/20260220204047-Config.rsc | 3416 ++++++++++++++ .../20260220/20260220222019-Binary.backup | Bin 0 -> 164118 bytes .../20260220/20260220222019-Config.rsc | 3418 ++++++++++++++ .../20260221/20260221102020-Binary.backup | Bin 0 -> 164118 bytes .../20260221/20260221102020-Config.rsc | 3418 ++++++++++++++ .../20260224/20260224232025-Binary.backup | Bin 0 -> 164118 bytes .../20260224/20260224233249-Binary.backup | Bin 0 -> 164118 bytes .../20260224/20260224233249-Config.rsc | 3418 ++++++++++++++ .../20260226/20260226172010-Binary.backup | Bin 0 -> 164118 bytes .../20260226/20260226172010-Config.rsc | 3418 ++++++++++++++ .../20260227/20260227150404-Binary.backup | Bin 0 -> 164118 bytes .../20260227/20260227154857-Binary.backup | Bin 0 -> 164118 bytes .../20260227/20260227154857-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228043326-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228044010-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228044739-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228050011-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228050306-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228050306-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228051209-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228051209-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228051343-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228051343-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228051618-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228051618-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228051910-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228051910-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228052011-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228052011-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228055330-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228055330-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228060011-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228060011-Config.rsc | 3418 ++++++++++++++ .../20260228/20260228062011-Binary.backup | Bin 0 -> 164118 bytes .../20260228/20260228062011-Config.rsc | 3418 ++++++++++++++ .../20260302/20260302143125-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302143125-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302144012-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302144012-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302150011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302150011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302152011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302152011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302154011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302154011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302160010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302160010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302162011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302162011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302164010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302164010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302170010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302170010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302172010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302172010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302174010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302174010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302180010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302180010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302182010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302182010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302184010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302184010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302190010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302190010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302192011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302192011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302194011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302194011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302200012-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302200012-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302202010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302202010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302204010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302204010-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302210011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302210011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302212011-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302212011-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302212925-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302212925-Config.rsc | 3946 ++++++++++++++++ .../20260302/20260302214010-Binary.backup | Bin 0 -> 181082 bytes .../20260302/20260302214010-Config.rsc | 3946 ++++++++++++++++ .../20260220/20260220102624-Diff-Config.rsc | 0 .../20260220/20260220103508-Diff-Config.rsc | 8 + .../20260220/20260220144020-Diff-Config.rsc | 4 + .../20260220/20260220204047-Diff-Config.rsc | 10 + .../20260220/20260220222019-Diff-Config.rsc | 10 + .../20260221/20260221102020-Diff-Config.rsc | 4 + .../20260224/20260224232025-Diff-Config.rsc | 0 .../20260224/20260224233249-Diff-Config.rsc | 0 .../20260226/20260226172010-Diff-Config.rsc | 4 + .../20260227/20260227150404-Diff-Config.rsc | 0 .../20260227/20260227154857-Diff-Config.rsc | 0 .../20260228/20260228043326-Diff-Config.rsc | 4 + .../20260228/20260228044010-Diff-Config.rsc | 4 + .../20260228/20260228044739-Diff-Config.rsc | 4 + .../20260228/20260228050011-Diff-Config.rsc | 4 + .../20260228/20260228050306-Diff-Config.rsc | 4 + .../20260228/20260228051209-Diff-Config.rsc | 4 + .../20260228/20260228051343-Diff-Config.rsc | 4 + .../20260228/20260228051618-Diff-Config.rsc | 4 + .../20260228/20260228051910-Diff-Config.rsc | 4 + .../20260228/20260228052011-Diff-Config.rsc | 4 + .../20260228/20260228055330-Diff-Config.rsc | 4 + .../20260228/20260228060011-Diff-Config.rsc | 4 + .../20260228/20260228062011-Diff-Config.rsc | 4 + .../20260302/20260302143125-Diff-Config.rsc | 2891 ++++++++++++ .../20260302/20260302144012-Diff-Config.rsc | 4 + .../20260302/20260302150011-Diff-Config.rsc | 4 + .../20260302/20260302152011-Diff-Config.rsc | 4 + .../20260302/20260302154011-Diff-Config.rsc | 4 + .../20260302/20260302160010-Diff-Config.rsc | 4 + .../20260302/20260302162011-Diff-Config.rsc | 4 + .../20260302/20260302164010-Diff-Config.rsc | 4 + .../20260302/20260302170010-Diff-Config.rsc | 4 + .../20260302/20260302172010-Diff-Config.rsc | 4 + .../20260302/20260302174010-Diff-Config.rsc | 4 + .../20260302/20260302180010-Diff-Config.rsc | 4 + .../20260302/20260302182010-Diff-Config.rsc | 4 + .../20260302/20260302184010-Diff-Config.rsc | 4 + .../20260302/20260302190010-Diff-Config.rsc | 4 + .../20260302/20260302192011-Diff-Config.rsc | 4 + .../20260302/20260302194011-Diff-Config.rsc | 4 + .../20260302/20260302200012-Diff-Config.rsc | 4 + .../20260302/20260302202010-Diff-Config.rsc | 8 + .../20260302/20260302204010-Diff-Config.rsc | 4 + .../20260302/20260302210011-Diff-Config.rsc | 4 + .../20260302/20260302212011-Diff-Config.rsc | 4 + .../20260302/20260302212925-Diff-Config.rsc | 4 + .../20260302/20260302214010-Diff-Config.rsc | 4 + 547 files changed, 601627 insertions(+) create mode 100644 .gitignore create mode 100644 MikroMaster/20260220/20260220092832-Binary.backup create mode 100644 MikroMaster/20260220/20260220092832-Config.rsc create mode 100644 MikroMaster/20260220/20260220110005-Binary.backup create mode 100644 MikroMaster/20260220/20260220110005-Config.rsc create mode 100644 MikroMaster/20260220/20260220110205-Binary.backup create mode 100644 MikroMaster/20260220/20260220110205-Config.rsc create mode 100644 MikroMaster/20260220/20260220110853-Binary.backup create mode 100644 MikroMaster/20260220/20260220110853-Config.rsc create mode 100644 MikroMaster/20260220/20260220111036-Binary.backup create mode 100644 MikroMaster/20260220/20260220111036-Config.rsc create mode 100644 MikroMaster/20260220/20260220142012-Binary.backup create mode 100644 MikroMaster/20260220/20260220142012-Config.rsc create mode 100644 MikroMaster/20260220/20260220190012-Binary.backup create mode 100644 MikroMaster/20260220/20260220190012-Config.rsc create mode 100644 MikroMaster/20260220/20260220210012-Binary.backup create mode 100644 MikroMaster/20260220/20260220210012-Config.rsc create mode 100644 MikroMaster/20260221/20260221130011-Binary.backup create mode 100644 MikroMaster/20260221/20260221130011-Config.rsc create mode 100644 MikroMaster/20260224/20260224050012-Binary.backup create mode 100644 MikroMaster/20260224/20260224050012-Config.rsc create mode 100644 MikroMaster/20260225/20260225004202-Binary.backup create mode 100644 MikroMaster/20260225/20260225004202-Config.rsc create mode 100644 MikroMaster/20260225/20260225012726-Binary.backup create mode 100644 MikroMaster/20260225/20260225012726-Config.rsc create mode 100644 MikroMaster/20260225/20260225120026-Binary.backup create mode 100644 MikroMaster/20260225/20260225120026-Config.rsc create mode 100644 MikroMaster/20260225/20260225150026-Binary.backup create mode 100644 MikroMaster/20260225/20260225150026-Config.rsc create mode 100644 MikroMaster/20260226/20260226084004-Binary.backup create mode 100644 MikroMaster/20260226/20260226084004-Config.rsc create mode 100644 MikroMaster/20260226/20260226092005-Binary.backup create mode 100644 MikroMaster/20260226/20260226092005-Config.rsc create mode 100644 MikroMaster/20260226/20260226220005-Binary.backup create mode 100644 MikroMaster/20260226/20260226220005-Config.rsc create mode 100644 MikroMaster/20260227/20260227150358-Binary.backup create mode 100644 MikroMaster/20260227/20260227154850-Binary.backup create mode 100644 MikroMaster/20260227/20260227154850-Config.rsc create mode 100644 MikroMaster/20260228/20260228043319-Config.rsc create mode 100644 MikroMaster/20260228/20260228044004-Config.rsc create mode 100644 MikroMaster/20260228/20260228044733-Binary.backup create mode 100644 MikroMaster/20260228/20260228050004-Binary.backup create mode 100644 MikroMaster/20260228/20260228050259-Binary.backup create mode 100644 MikroMaster/20260228/20260228050259-Config.rsc create mode 100644 MikroMaster/20260228/20260228051202-Binary.backup create mode 100644 MikroMaster/20260228/20260228051202-Config.rsc create mode 100644 MikroMaster/20260228/20260228051337-Binary.backup create mode 100644 MikroMaster/20260228/20260228051337-Config.rsc create mode 100644 MikroMaster/20260228/20260228051612-Binary.backup create mode 100644 MikroMaster/20260228/20260228051612-Config.rsc create mode 100644 MikroMaster/20260228/20260228051903-Binary.backup create mode 100644 MikroMaster/20260228/20260228051903-Config.rsc create mode 100644 MikroMaster/20260228/20260228052004-Binary.backup create mode 100644 MikroMaster/20260228/20260228052004-Config.rsc create mode 100644 MikroMaster/20260228/20260228055323-Binary.backup create mode 100644 MikroMaster/20260228/20260228055323-Config.rsc create mode 100644 MikroMaster/20260228/20260228060004-Binary.backup create mode 100644 MikroMaster/20260228/20260228060004-Config.rsc create mode 100644 MikroMaster/20260228/20260228062004-Binary.backup create mode 100644 MikroMaster/20260228/20260228062004-Config.rsc create mode 100644 MikroMaster/20260302/20260302143118-Binary.backup create mode 100644 MikroMaster/20260302/20260302143118-Config.rsc create mode 100644 MikroMaster/20260302/20260302144005-Binary.backup create mode 100644 MikroMaster/20260302/20260302144005-Config.rsc create mode 100644 MikroMaster/20260302/20260302150004-Binary.backup create mode 100644 MikroMaster/20260302/20260302150004-Config.rsc create mode 100644 MikroMaster/20260302/20260302152005-Binary.backup create mode 100644 MikroMaster/20260302/20260302152005-Config.rsc create mode 100644 MikroMaster/20260302/20260302154004-Binary.backup create mode 100644 MikroMaster/20260302/20260302154004-Config.rsc create mode 100644 MikroMaster/20260302/20260302160004-Binary.backup create mode 100644 MikroMaster/20260302/20260302160004-Config.rsc create mode 100644 MikroMaster/20260302/20260302162004-Binary.backup create mode 100644 MikroMaster/20260302/20260302162004-Config.rsc create mode 100644 MikroMaster/20260302/20260302164004-Binary.backup create mode 100644 MikroMaster/20260302/20260302164004-Config.rsc create mode 100644 MikroMaster/20260302/20260302170004-Binary.backup create mode 100644 MikroMaster/20260302/20260302170004-Config.rsc create mode 100644 MikroMaster/20260302/20260302172004-Binary.backup create mode 100644 MikroMaster/20260302/20260302172004-Config.rsc create mode 100644 MikroMaster/20260302/20260302174004-Binary.backup create mode 100644 MikroMaster/20260302/20260302174004-Config.rsc create mode 100644 MikroMaster/20260302/20260302180004-Binary.backup create mode 100644 MikroMaster/20260302/20260302180004-Config.rsc create mode 100644 MikroMaster/20260302/20260302182004-Binary.backup create mode 100644 MikroMaster/20260302/20260302182004-Config.rsc create mode 100644 MikroMaster/20260302/20260302184004-Binary.backup create mode 100644 MikroMaster/20260302/20260302184004-Config.rsc create mode 100644 MikroMaster/20260302/20260302190003-Binary.backup create mode 100644 MikroMaster/20260302/20260302190003-Config.rsc create mode 100644 MikroMaster/20260302/20260302192004-Binary.backup create mode 100644 MikroMaster/20260302/20260302192004-Config.rsc create mode 100644 MikroMaster/20260302/20260302194004-Binary.backup create mode 100644 MikroMaster/20260302/20260302194004-Config.rsc create mode 100644 MikroMaster/20260302/20260302200004-Binary.backup create mode 100644 MikroMaster/20260302/20260302200004-Config.rsc create mode 100644 MikroMaster/20260302/20260302202004-Binary.backup create mode 100644 MikroMaster/20260302/20260302202004-Config.rsc create mode 100644 MikroMaster/20260302/20260302204004-Binary.backup create mode 100644 MikroMaster/20260302/20260302204004-Config.rsc create mode 100644 MikroMaster/20260302/20260302210004-Binary.backup create mode 100644 MikroMaster/20260302/20260302210004-Config.rsc create mode 100644 MikroMaster/20260302/20260302212004-Binary.backup create mode 100644 MikroMaster/20260302/20260302212004-Config.rsc create mode 100644 MikroMaster/20260302/20260302212918-Binary.backup create mode 100644 MikroMaster/20260302/20260302212918-Config.rsc create mode 100644 MikroMaster/20260302/20260302214004-Binary.backup create mode 100644 MikroMaster/20260302/20260302214004-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220092832-Diff-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220110005-Diff-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220110205-Diff-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220110853-Diff-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220111036-Diff-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220142012-Diff-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220190012-Diff-Config.rsc create mode 100644 MikroMaster/history/20260220/20260220210012-Diff-Config.rsc create mode 100644 MikroMaster/history/20260221/20260221130011-Diff-Config.rsc create mode 100644 MikroMaster/history/20260224/20260224050012-Diff-Config.rsc create mode 100644 MikroMaster/history/20260225/20260225004202-Diff-Config.rsc create mode 100644 MikroMaster/history/20260225/20260225012726-Diff-Config.rsc create mode 100644 MikroMaster/history/20260225/20260225120026-Diff-Config.rsc create mode 100644 MikroMaster/history/20260225/20260225150026-Diff-Config.rsc create mode 100644 MikroMaster/history/20260226/20260226084004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260226/20260226092005-Diff-Config.rsc create mode 100644 MikroMaster/history/20260226/20260226220005-Diff-Config.rsc create mode 100644 MikroMaster/history/20260227/20260227150358-Diff-Config.rsc create mode 100644 MikroMaster/history/20260227/20260227154850-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228043319-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228044004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228044733-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228050004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228050259-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228051202-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228051337-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228051612-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228051903-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228052004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228055323-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228060004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260228/20260228062004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302143118-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302144005-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302150004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302152005-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302154004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302160004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302162004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302164004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302170004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302172004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302174004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302180004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302182004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302184004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302190003-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302192004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302194004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302200004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302202004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302204004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302210004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302212004-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302212918-Diff-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302214004-Diff-Config.rsc create mode 100644 MikroNUC/20260220/20260220072118-Binary.backup create mode 100644 MikroNUC/20260220/20260220072118-Config.rsc create mode 100644 MikroNUC/20260220/20260220072834-Binary.backup create mode 100644 MikroNUC/20260220/20260220072834-Config.rsc create mode 100644 MikroNUC/20260220/20260220072919-Binary.backup create mode 100644 MikroNUC/20260220/20260220072919-Config.rsc create mode 100644 MikroNUC/20260220/20260220083844-Binary.backup create mode 100644 MikroNUC/20260220/20260220083844-Config.rsc create mode 100644 MikroNUC/20260220/20260220083924-Binary.backup create mode 100644 MikroNUC/20260220/20260220083924-Config.rsc create mode 100644 MikroNUC/20260220/20260220085626-Binary.backup create mode 100644 MikroNUC/20260220/20260220085626-Config.rsc create mode 100644 MikroNUC/20260220/20260220085921-Binary.backup create mode 100644 MikroNUC/20260220/20260220085921-Config.rsc create mode 100644 MikroNUC/20260220/20260220085933-Binary.backup create mode 100644 MikroNUC/20260220/20260220085933-Config.rsc create mode 100644 MikroNUC/20260220/20260220090536-Binary.backup create mode 100644 MikroNUC/20260220/20260220090536-Config.rsc create mode 100644 MikroNUC/20260220/20260220090557-Binary.backup create mode 100644 MikroNUC/20260220/20260220090557-Config.rsc create mode 100644 MikroNUC/20260220/20260220103113-Binary.backup create mode 100644 MikroNUC/20260220/20260220103113-Config.rsc create mode 100644 MikroNUC/20260220/20260220103550-Binary.backup create mode 100644 MikroNUC/20260220/20260220103550-Config.rsc create mode 100644 MikroNUC/20260220/20260220130018-Binary.backup create mode 100644 MikroNUC/20260220/20260220130018-Config.rsc create mode 100644 MikroNUC/20260220/20260220132007-Binary.backup create mode 100644 MikroNUC/20260220/20260220132007-Config.rsc create mode 100644 MikroNUC/20260220/20260220134006-Binary.backup create mode 100644 MikroNUC/20260220/20260220134006-Config.rsc create mode 100644 MikroNUC/20260220/20260220140006-Binary.backup create mode 100644 MikroNUC/20260220/20260220140006-Config.rsc create mode 100644 MikroNUC/20260220/20260220192007-Binary.backup create mode 100644 MikroNUC/20260220/20260220192007-Config.rsc create mode 100644 MikroNUC/20260220/20260220212007-Binary.backup create mode 100644 MikroNUC/20260220/20260220212007-Config.rsc create mode 100644 MikroNUC/20260220/20260220214006-Binary.backup create mode 100644 MikroNUC/20260220/20260220214006-Config.rsc create mode 100644 MikroNUC/20260220/20260220220007-Binary.backup create mode 100644 MikroNUC/20260220/20260220220007-Config.rsc create mode 100644 MikroNUC/20260221/20260221232006-Binary.backup create mode 100644 MikroNUC/20260221/20260221232006-Config.rsc create mode 100644 MikroNUC/20260222/20260222002006-Binary.backup create mode 100644 MikroNUC/20260222/20260222002006-Config.rsc create mode 100644 MikroNUC/20260222/20260222004007-Binary.backup create mode 100644 MikroNUC/20260222/20260222004007-Config.rsc create mode 100644 MikroNUC/20260222/20260222010006-Binary.backup create mode 100644 MikroNUC/20260222/20260222010006-Config.rsc create mode 100644 MikroNUC/20260222/20260222012007-Binary.backup create mode 100644 MikroNUC/20260222/20260222012007-Config.rsc create mode 100644 MikroNUC/20260222/20260222014006-Binary.backup create mode 100644 MikroNUC/20260222/20260222014006-Config.rsc create mode 100644 MikroNUC/20260224/20260224122252-Binary.backup create mode 100644 MikroNUC/20260224/20260224122252-Config.rsc create mode 100644 MikroNUC/20260224/20260224122441-Binary.backup create mode 100644 MikroNUC/20260224/20260224122441-Config.rsc create mode 100644 MikroNUC/20260224/20260224122638-Binary.backup create mode 100644 MikroNUC/20260224/20260224122638-Config.rsc create mode 100644 MikroNUC/20260224/20260224192006-Binary.backup create mode 100644 MikroNUC/20260224/20260224192006-Config.rsc create mode 100644 MikroNUC/20260224/20260224194007-Binary.backup create mode 100644 MikroNUC/20260224/20260224194007-Config.rsc create mode 100644 MikroNUC/20260224/20260224214007-Binary.backup create mode 100644 MikroNUC/20260224/20260224214007-Config.rsc create mode 100644 MikroNUC/20260224/20260224215052-Binary.backup create mode 100644 MikroNUC/20260224/20260224215052-Config.rsc create mode 100644 MikroNUC/20260224/20260224215237-Binary.backup create mode 100644 MikroNUC/20260224/20260224215237-Config.rsc create mode 100644 MikroNUC/20260224/20260224215620-Binary.backup create mode 100644 MikroNUC/20260224/20260224215620-Config.rsc create mode 100644 MikroNUC/20260224/20260224220006-Binary.backup create mode 100644 MikroNUC/20260224/20260224220006-Config.rsc create mode 100644 MikroNUC/20260224/20260224220134-Binary.backup create mode 100644 MikroNUC/20260224/20260224220134-Config.rsc create mode 100644 MikroNUC/20260224/20260224223439-Binary.backup create mode 100644 MikroNUC/20260224/20260224223439-Config.rsc create mode 100644 MikroNUC/20260224/20260224230007-Binary.backup create mode 100644 MikroNUC/20260224/20260224230007-Config.rsc create mode 100644 MikroNUC/20260224/20260224230243-Binary.backup create mode 100644 MikroNUC/20260224/20260224230243-Config.rsc create mode 100644 MikroNUC/20260224/20260224230525-Binary.backup create mode 100644 MikroNUC/20260224/20260224230525-Config.rsc create mode 100644 MikroNUC/20260224/20260224230855-Binary.backup create mode 100644 MikroNUC/20260224/20260224230855-Config.rsc create mode 100644 MikroNUC/20260224/20260224231054-Binary.backup create mode 100644 MikroNUC/20260224/20260224231054-Config.rsc create mode 100644 MikroNUC/20260224/20260224231651-Binary.backup create mode 100644 MikroNUC/20260224/20260224231651-Config.rsc create mode 100644 MikroNUC/20260224/20260224231900-Binary.backup create mode 100644 MikroNUC/20260224/20260224231900-Config.rsc create mode 100644 MikroNUC/20260224/20260224232005-Binary.backup create mode 100644 MikroNUC/20260224/20260224232005-Config.rsc create mode 100644 MikroNUC/20260227/20260227162307-Config.rsc create mode 100644 MikroNUC/20260228/20260228043316-Config.rsc create mode 100644 MikroNUC/20260228/20260228044001-Config.rsc create mode 100644 MikroNUC/20260228/20260228044730-Binary.backup create mode 100644 MikroNUC/20260228/20260228050001-Binary.backup create mode 100644 MikroNUC/20260228/20260228050256-Binary.backup create mode 100644 MikroNUC/20260228/20260228050256-Config.rsc create mode 100644 MikroNUC/20260228/20260228051159-Binary.backup create mode 100644 MikroNUC/20260228/20260228051159-Config.rsc create mode 100644 MikroNUC/20260228/20260228051334-Binary.backup create mode 100644 MikroNUC/20260228/20260228051334-Config.rsc create mode 100644 MikroNUC/20260228/20260228051609-Binary.backup create mode 100644 MikroNUC/20260228/20260228051609-Config.rsc create mode 100644 MikroNUC/20260228/20260228051900-Binary.backup create mode 100644 MikroNUC/20260228/20260228051900-Config.rsc create mode 100644 MikroNUC/20260228/20260228052001-Binary.backup create mode 100644 MikroNUC/20260228/20260228052001-Config.rsc create mode 100644 MikroNUC/20260228/20260228055320-Binary.backup create mode 100644 MikroNUC/20260228/20260228055320-Config.rsc create mode 100644 MikroNUC/20260228/20260228060001-Binary.backup create mode 100644 MikroNUC/20260228/20260228060001-Config.rsc create mode 100644 MikroNUC/20260228/20260228062001-Binary.backup create mode 100644 MikroNUC/20260228/20260228062001-Config.rsc create mode 100644 MikroNUC/20260302/20260302143114-Binary.backup create mode 100644 MikroNUC/20260302/20260302143114-Config.rsc create mode 100644 MikroNUC/20260302/20260302144001-Binary.backup create mode 100644 MikroNUC/20260302/20260302144001-Config.rsc create mode 100644 MikroNUC/20260302/20260302150001-Binary.backup create mode 100644 MikroNUC/20260302/20260302150001-Config.rsc create mode 100644 MikroNUC/20260302/20260302152002-Binary.backup create mode 100644 MikroNUC/20260302/20260302152002-Config.rsc create mode 100644 MikroNUC/20260302/20260302154001-Binary.backup create mode 100644 MikroNUC/20260302/20260302154001-Config.rsc create mode 100644 MikroNUC/20260302/20260302160001-Binary.backup create mode 100644 MikroNUC/20260302/20260302160001-Config.rsc create mode 100644 MikroNUC/20260302/20260302162001-Binary.backup create mode 100644 MikroNUC/20260302/20260302162001-Config.rsc create mode 100644 MikroNUC/20260302/20260302164001-Binary.backup create mode 100644 MikroNUC/20260302/20260302164001-Config.rsc create mode 100644 MikroNUC/20260302/20260302170001-Binary.backup create mode 100644 MikroNUC/20260302/20260302170001-Config.rsc create mode 100644 MikroNUC/20260302/20260302172001-Binary.backup create mode 100644 MikroNUC/20260302/20260302172001-Config.rsc create mode 100644 MikroNUC/20260302/20260302174001-Binary.backup create mode 100644 MikroNUC/20260302/20260302174001-Config.rsc create mode 100644 MikroNUC/20260302/20260302180001-Binary.backup create mode 100644 MikroNUC/20260302/20260302180001-Config.rsc create mode 100644 MikroNUC/20260302/20260302182001-Binary.backup create mode 100644 MikroNUC/20260302/20260302182001-Config.rsc create mode 100644 MikroNUC/20260302/20260302184001-Binary.backup create mode 100644 MikroNUC/20260302/20260302184001-Config.rsc create mode 100644 MikroNUC/20260302/20260302190001-Binary.backup create mode 100644 MikroNUC/20260302/20260302190001-Config.rsc create mode 100644 MikroNUC/20260302/20260302192001-Binary.backup create mode 100644 MikroNUC/20260302/20260302192001-Config.rsc create mode 100644 MikroNUC/20260302/20260302194001-Binary.backup create mode 100644 MikroNUC/20260302/20260302194001-Config.rsc create mode 100644 MikroNUC/20260302/20260302200001-Binary.backup create mode 100644 MikroNUC/20260302/20260302200001-Config.rsc create mode 100644 MikroNUC/20260302/20260302202001-Binary.backup create mode 100644 MikroNUC/20260302/20260302202001-Config.rsc create mode 100644 MikroNUC/20260302/20260302204001-Binary.backup create mode 100644 MikroNUC/20260302/20260302204001-Config.rsc create mode 100644 MikroNUC/20260302/20260302210001-Binary.backup create mode 100644 MikroNUC/20260302/20260302210001-Config.rsc create mode 100644 MikroNUC/20260302/20260302212001-Binary.backup create mode 100644 MikroNUC/20260302/20260302212001-Config.rsc create mode 100644 MikroNUC/20260302/20260302212913-Binary.backup create mode 100644 MikroNUC/20260302/20260302212913-Config.rsc create mode 100644 MikroNUC/20260302/20260302214002-Binary.backup create mode 100644 MikroNUC/20260302/20260302214002-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220072118-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220072834-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220072919-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220083844-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220083924-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220085626-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220085921-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220085933-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220090536-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220090557-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220103113-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220103550-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220130018-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220132007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220134006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220140006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220192007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220212007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220214006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260220/20260220220007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260221/20260221232006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260222/20260222002006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260222/20260222004007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260222/20260222010006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260222/20260222012007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260222/20260222014006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224122252-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224122441-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224122638-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224192006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224194007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224214007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224215052-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224215237-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224215620-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224220006-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224220134-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224223439-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224230007-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224230243-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224230525-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224230855-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224231054-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224231651-Diff-Config.rsc create mode 100644 MikroNUC/history/20260224/20260224231900-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228043316-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228044001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228044730-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228050001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228050256-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228051159-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228051334-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228051609-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228051900-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228052001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228055320-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228060001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260228/20260228062001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302143114-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302144001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302150001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302152002-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302154001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302160001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302162001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302164001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302170001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302172001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302174001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302180001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302182001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302184001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302190001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302192001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302194001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302200001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302202001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302204001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302210001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302212001-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302212913-Diff-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302214002-Diff-Config.rsc create mode 100644 MikroYellow/20260220/20260220102624-Binary.backup create mode 100644 MikroYellow/20260220/20260220102624-Config.rsc create mode 100644 MikroYellow/20260220/20260220103508-Binary.backup create mode 100644 MikroYellow/20260220/20260220103508-Config.rsc create mode 100644 MikroYellow/20260220/20260220144020-Binary.backup create mode 100644 MikroYellow/20260220/20260220144020-Config.rsc create mode 100644 MikroYellow/20260220/20260220204047-Binary.backup create mode 100644 MikroYellow/20260220/20260220204047-Config.rsc create mode 100644 MikroYellow/20260220/20260220222019-Binary.backup create mode 100644 MikroYellow/20260220/20260220222019-Config.rsc create mode 100644 MikroYellow/20260221/20260221102020-Binary.backup create mode 100644 MikroYellow/20260221/20260221102020-Config.rsc create mode 100644 MikroYellow/20260224/20260224232025-Binary.backup create mode 100644 MikroYellow/20260224/20260224233249-Binary.backup create mode 100644 MikroYellow/20260224/20260224233249-Config.rsc create mode 100644 MikroYellow/20260226/20260226172010-Binary.backup create mode 100644 MikroYellow/20260226/20260226172010-Config.rsc create mode 100644 MikroYellow/20260227/20260227150404-Binary.backup create mode 100644 MikroYellow/20260227/20260227154857-Binary.backup create mode 100644 MikroYellow/20260227/20260227154857-Config.rsc create mode 100644 MikroYellow/20260228/20260228043326-Config.rsc create mode 100644 MikroYellow/20260228/20260228044010-Config.rsc create mode 100644 MikroYellow/20260228/20260228044739-Binary.backup create mode 100644 MikroYellow/20260228/20260228050011-Binary.backup create mode 100644 MikroYellow/20260228/20260228050306-Binary.backup create mode 100644 MikroYellow/20260228/20260228050306-Config.rsc create mode 100644 MikroYellow/20260228/20260228051209-Binary.backup create mode 100644 MikroYellow/20260228/20260228051209-Config.rsc create mode 100644 MikroYellow/20260228/20260228051343-Binary.backup create mode 100644 MikroYellow/20260228/20260228051343-Config.rsc create mode 100644 MikroYellow/20260228/20260228051618-Binary.backup create mode 100644 MikroYellow/20260228/20260228051618-Config.rsc create mode 100644 MikroYellow/20260228/20260228051910-Binary.backup create mode 100644 MikroYellow/20260228/20260228051910-Config.rsc create mode 100644 MikroYellow/20260228/20260228052011-Binary.backup create mode 100644 MikroYellow/20260228/20260228052011-Config.rsc create mode 100644 MikroYellow/20260228/20260228055330-Binary.backup create mode 100644 MikroYellow/20260228/20260228055330-Config.rsc create mode 100644 MikroYellow/20260228/20260228060011-Binary.backup create mode 100644 MikroYellow/20260228/20260228060011-Config.rsc create mode 100644 MikroYellow/20260228/20260228062011-Binary.backup create mode 100644 MikroYellow/20260228/20260228062011-Config.rsc create mode 100644 MikroYellow/20260302/20260302143125-Binary.backup create mode 100644 MikroYellow/20260302/20260302143125-Config.rsc create mode 100644 MikroYellow/20260302/20260302144012-Binary.backup create mode 100644 MikroYellow/20260302/20260302144012-Config.rsc create mode 100644 MikroYellow/20260302/20260302150011-Binary.backup create mode 100644 MikroYellow/20260302/20260302150011-Config.rsc create mode 100644 MikroYellow/20260302/20260302152011-Binary.backup create mode 100644 MikroYellow/20260302/20260302152011-Config.rsc create mode 100644 MikroYellow/20260302/20260302154011-Binary.backup create mode 100644 MikroYellow/20260302/20260302154011-Config.rsc create mode 100644 MikroYellow/20260302/20260302160010-Binary.backup create mode 100644 MikroYellow/20260302/20260302160010-Config.rsc create mode 100644 MikroYellow/20260302/20260302162011-Binary.backup create mode 100644 MikroYellow/20260302/20260302162011-Config.rsc create mode 100644 MikroYellow/20260302/20260302164010-Binary.backup create mode 100644 MikroYellow/20260302/20260302164010-Config.rsc create mode 100644 MikroYellow/20260302/20260302170010-Binary.backup create mode 100644 MikroYellow/20260302/20260302170010-Config.rsc create mode 100644 MikroYellow/20260302/20260302172010-Binary.backup create mode 100644 MikroYellow/20260302/20260302172010-Config.rsc create mode 100644 MikroYellow/20260302/20260302174010-Binary.backup create mode 100644 MikroYellow/20260302/20260302174010-Config.rsc create mode 100644 MikroYellow/20260302/20260302180010-Binary.backup create mode 100644 MikroYellow/20260302/20260302180010-Config.rsc create mode 100644 MikroYellow/20260302/20260302182010-Binary.backup create mode 100644 MikroYellow/20260302/20260302182010-Config.rsc create mode 100644 MikroYellow/20260302/20260302184010-Binary.backup create mode 100644 MikroYellow/20260302/20260302184010-Config.rsc create mode 100644 MikroYellow/20260302/20260302190010-Binary.backup create mode 100644 MikroYellow/20260302/20260302190010-Config.rsc create mode 100644 MikroYellow/20260302/20260302192011-Binary.backup create mode 100644 MikroYellow/20260302/20260302192011-Config.rsc create mode 100644 MikroYellow/20260302/20260302194011-Binary.backup create mode 100644 MikroYellow/20260302/20260302194011-Config.rsc create mode 100644 MikroYellow/20260302/20260302200012-Binary.backup create mode 100644 MikroYellow/20260302/20260302200012-Config.rsc create mode 100644 MikroYellow/20260302/20260302202010-Binary.backup create mode 100644 MikroYellow/20260302/20260302202010-Config.rsc create mode 100644 MikroYellow/20260302/20260302204010-Binary.backup create mode 100644 MikroYellow/20260302/20260302204010-Config.rsc create mode 100644 MikroYellow/20260302/20260302210011-Binary.backup create mode 100644 MikroYellow/20260302/20260302210011-Config.rsc create mode 100644 MikroYellow/20260302/20260302212011-Binary.backup create mode 100644 MikroYellow/20260302/20260302212011-Config.rsc create mode 100644 MikroYellow/20260302/20260302212925-Binary.backup create mode 100644 MikroYellow/20260302/20260302212925-Config.rsc create mode 100644 MikroYellow/20260302/20260302214010-Binary.backup create mode 100644 MikroYellow/20260302/20260302214010-Config.rsc create mode 100644 MikroYellow/history/20260220/20260220102624-Diff-Config.rsc create mode 100644 MikroYellow/history/20260220/20260220103508-Diff-Config.rsc create mode 100644 MikroYellow/history/20260220/20260220144020-Diff-Config.rsc create mode 100644 MikroYellow/history/20260220/20260220204047-Diff-Config.rsc create mode 100644 MikroYellow/history/20260220/20260220222019-Diff-Config.rsc create mode 100644 MikroYellow/history/20260221/20260221102020-Diff-Config.rsc create mode 100644 MikroYellow/history/20260224/20260224232025-Diff-Config.rsc create mode 100644 MikroYellow/history/20260224/20260224233249-Diff-Config.rsc create mode 100644 MikroYellow/history/20260226/20260226172010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260227/20260227150404-Diff-Config.rsc create mode 100644 MikroYellow/history/20260227/20260227154857-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228043326-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228044010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228044739-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228050011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228050306-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228051209-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228051343-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228051618-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228051910-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228052011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228055330-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228060011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260228/20260228062011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302143125-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302144012-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302150011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302152011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302154011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302160010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302162011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302164010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302170010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302172010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302174010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302180010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302182010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302184010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302190010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302192011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302194011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302200012-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302202010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302204010-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302210011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302212011-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302212925-Diff-Config.rsc create mode 100644 MikroYellow/history/20260302/20260302214010-Diff-Config.rsc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d2a7d1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.ssh +**/Precedent-Config.rsc diff --git a/MikroMaster/20260220/20260220092832-Binary.backup b/MikroMaster/20260220/20260220092832-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d5f476ed22fa5d414fe2e485ff67a99cec23ee19 GIT binary patch literal 288928 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 LSxBbYvD1G8&*iY# literal 0 HcmV?d00001 diff --git a/MikroMaster/20260220/20260220092832-Config.rsc b/MikroMaster/20260220/20260220092832-Config.rsc new file mode 100644 index 0000000..74565a0 --- /dev/null +++ b/MikroMaster/20260220/20260220092832-Config.rsc @@ -0,0 +1,3956 @@ +# 2026-02-20 09:28:28 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260220/20260220110005-Binary.backup b/MikroMaster/20260220/20260220110005-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ea7b8b4dd9b180fb276e55adc94d10805d9d7a31 GIT binary patch literal 288924 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 F{|)t?uuT8} literal 0 HcmV?d00001 diff --git a/MikroMaster/20260220/20260220110005-Config.rsc b/MikroMaster/20260220/20260220110005-Config.rsc new file mode 100644 index 0000000..6065ec7 --- /dev/null +++ b/MikroMaster/20260220/20260220110005-Config.rsc @@ -0,0 +1,3954 @@ +# 2026-02-20 11:00:01 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260220/20260220110205-Binary.backup b/MikroMaster/20260220/20260220110205-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..7a2b4472335b759e6022c105a9eddee27ae9e2e5 GIT binary patch literal 288926 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�+>Eg!7e7t^51;`PCBJO!RDQ3K&Bg$^kLnMqD$)+b^h^I9e{ ze^AePk^Vwzm_RQP{gw#ly~y-8)cg%V|G?!fT%INJ-CoQNobjPUKEci35czQQ-S5y| zzsH@|;OhG$e*Y=a)X^=0gZp|bhpbP;YEtQ7GODCfHOcOOq6Pm*@>t(O%t%K!NyOuz$ zM`*S72mCFOb;VJtBQ8P%Eb~Ba&0Oe-#!>B~S^|(h*gtRyF)s^$x|50M zIW2*=yzqeyp_afweZBHn^w6Ed$n%buS(>`_n0xE(@X}OIOWrF3d3~=W#lHP?o zL2czH1TVtrD0OzHs8v7Bvei$s;6+gOc@c8-A{53`AZ2xmN)ArZA-d0?&%IN$sMtrc z&y`2C)TKvM%H|Q3M2{#uqpm%oa^h}yHqGwPzCyV}rHt-S&*#$}N^pl}bQlQp(s6}w z7}PZ_S}?P|abZJK-7MWI8K?rj0M~m^N1*(@NRAqoKogR2vTq zttT1^wRarIosd`!#|KZa;*Sqj)HN8P*$b#8P_&7p;!PxZPA0ij8cMRq%OL8Ni-!*- zIU$`)K7T8gl6xzCq4tjIKu70kMMJfj&=Ly{pN_)^93}m53<8dZj?UAngCU^NDrQAg ztRpG~qEaVBF%c2g$knz;c1M+3-X16LHb8rPnZsz0lQ}FNnm$D$I)PdO!&hKodGHD> z)?lT)oc)b?L)i+Fy@OT|{DHl4@eurpaQ2d6E2xr&;!?4KDvQuov_iL_F!1V^;juXsKdE8bsph=^cqke0nez zjK(_-*S)r{qu|!pJz&Km_WDXw**&ZU(H<4l z%XWIeIf3#QF}WxvsvLI+BE^;P>7mYGtV0Q(o>aQx>y@zo5QY#DE74Fm9q$fxRwsfT z3gZDc?1Pem>)f&%`mrY(N+}p7@guYhBJS|PcRjenPgq6jl|3Fm$&%MkvO4mmlu&mv zlHOS4r^+(JQ-naAo@gkX2&Owj?OIq8YZi<_oxzxJ7mN_psN;jdN&Bu6O81m7rSb>rN@j>ZlS%NEjZetcgcMQ$3M%sI#^@7>(kM6l&R)Qj+UI9;gvK zgb%*Q@mhL_B-Abp2}U*ph+;C5n4XLz)+rnDQ#U+-Mo22DcyzszoSsSt(~-~uNu_!s zr;1(pI)Z;9u!?9FNM?BsURiIdhEoNYKIF|A+S+Ty}U+0EK z5gVzzIt@>5Gy-3;s|SWay@^hIfHVY}vwAh74*z-CgUz7;AuR zkd90?*V@Mzqa_kz2-mtncq|Z>YY5p;XvR5+;XGc6M&msU?NT>rD}i>bhE_gMuXIVU z3+Y%HrsLgUngC4WbWD?UOhdXN(WsKFVMcsSlC2e#v@BV+Y~e90+#qH}9Iqp;(h-+; z#X3w_-4&GK+fT<=spA`>R@sEIWNyo<)wvXOe;x4wI^yy~GHt?2Yg||S03F{U=Kd~E zDwf*2>hO{1rU^RIa=nlx9l>OI*P3Gd2sJ+hkr_~KQ)-9Dfy0Ln} z%G55VBsCS7<{B9Q=<**X

Fs_d12YtlwMW?00iRpB0fp~dsUNC}G42%=srQO7 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 IX2(wd4S_GPUH||9 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260220/20260220110205-Config.rsc b/MikroMaster/20260220/20260220110205-Config.rsc new file mode 100644 index 0000000..4b5f14b --- /dev/null +++ b/MikroMaster/20260220/20260220110205-Config.rsc @@ -0,0 +1,3955 @@ +# 2026-02-20 11:02:02 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260220/20260220110853-Binary.backup b/MikroMaster/20260220/20260220110853-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..9ecb87235992a9e99283d88d2027472235bbd5ef GIT binary patch literal 288928 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 I&5oV^8yD!ajQ{`u literal 0 HcmV?d00001 diff --git a/MikroMaster/20260220/20260220210012-Config.rsc b/MikroMaster/20260220/20260220210012-Config.rsc new file mode 100644 index 0000000..141963e --- /dev/null +++ b/MikroMaster/20260220/20260220210012-Config.rsc @@ -0,0 +1,3955 @@ +# 2026-02-20 21:00:08 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260221/20260221130011-Binary.backup b/MikroMaster/20260221/20260221130011-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..0eb693ae0061f2b55ad999701b41b91ad0c90eb9 GIT binary patch literal 288912 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 *#PYnsGm+kT<1{QFpfuGe>S?H(H=+qCmOj zqqLsx6HOy0O#9fsi^W>|Kv&1g+1;m9Yu=`J$Z@=WZ^+px8+=*rfgLVR;O8pOn-xT@ zS=dRiRl8_^_xSPU)LSQqjEJD+%v_u><;YsinudoNVP$u+X7IP?$}Y{eShFec^w3sq zFFPbo>))e{pSE;LgFXwb&N#2AJI`uqNY(KA-S%$T*!g4m$PRvkc(Gpd&rR!DU-Hp< z7`^K-*K1~WrjC@eH+DE2xE9g(Y1bi_W*n%?nzpmvOY3R*81wS|-iZf3$*>DuuzeZy zZR=j0%#2HIR!kpuaeF86wN)r>RQ!6Ax9P9b+Z3N?#`xGRuk)}|kCZZzVBUiZLzHV) zMvs~NLUsP^{@v7mm&|h&ZE4T_*7)@C*i&86Yh$0)Lt`9LhL8JbJT9X5L|fBCkNf)F z!1srZMa@dtS9=eonLDc*jf}}rCJs(&`{7p9PIlY2?-aYAcX*g}qw#Cz!0D9|;_mSd zMGX@c+>eYY&pI9IQ>XCd)gG0r?>66nU;all_stcNXK#NW`rRwH%6HT+NpP`2~O?jOW_@tdA-}l8n`ACEL>`3#v^JRY0*@MQJu5ZNZ?O?aF zpkU?xN>{6b;rxBG799;LzrE!|MfR$;r;7qwPN^Rf^~}ah9KUmZ_B!i>R|Y(?iE%oe zu9;uDC_a@ltbEwiROzb@+ESCdtPPjsr41JpK0c({S16{1%(~v6Ul!^RW)#`NfBb*} zOUFeO**A=^H64-GDn6&l=8e8l0T-W+U3z+U>H_=7X?^c`&P#2SRum;ujyW0ko>?*Y z`rfl`WnBj!ye)OOy6KJU#8zHg_V|<(a(D|~wwQ0Gn)YGrK0yR6@pj*^dXZbF&7Ro& zKtTO@i{sqeX9Wl>oYy{G!no)c8RGjiKcVH;Go`0?u6El#>#!+8n2QmXY2=7y(v9^kDqz%Ga|*@O2w@!D6k{6Gy3viTsolbH zTg(Q2u&m9$P~x~5#)9)SYg!o2#vJX;**qL)3o)F{#jr>_b2cAiv-ud#=I}(3SWCP) z)>L=>FLgYYNpYzS6vYV9GAR}a%cQWVnG^~-J5#Zw{KaM0F7w^oT0 zDObe`<9pi7jRU6jRlnGjTrgoKow>wY(6^fTQM7l{WKq4gDPl95X48k1jD9=ph24-b zGrcRymhHKhU-wm`=fNI>N0rbWff;NRA8ITb^?i|f#B={B}gvO2|& zX&)YMvw7aLiS~P~pNAgA8o|Y`bbHKpxDDFa{Du2O6@G6{=T)g~-(S6NcKQs)G2EF# zp*O`EW3GnZ7DsMOJ(SWCETUAi0QlKE?9u!f7B=w=uTV;CDp zXP8l_6wDJ&HljDfnqY4EF8NNQ9BVyGR_j?f#_^D;iQevwJ0CoU5M}nEj`!RUqSKH+ z=1X-(hl9tiC}nc`-YIV$x;t^js7)=6-?yk5yM*3jaac>At*59?u1Acg(vJ+8GGg7p zi?e*rPBhMW{JO*C6=xUJZD*g7edjt#K}Use>x~&QazV$a-g~ZnIGpfecCX|9ETvJ_ z+M_o6Ymi z=Ua#7w6ZiBZSnXN{d%>^;hImTk$0C_c~9$(3yxwlCLE(?NG6`{aDSTl^C`Qhtg?LB za;MQ|)tTobdL`XIL8rZuKG@sBb57~8cxS<$=(G4Nj?+c9jdv5u^tj$LHyJl-k~2N- zMgE$WNwRkDNp4deeUOe9OQDQ-;x;n;^WemS3)n^uI!L)O;aS)r{CH# z_0t%HEWvgJn>HIEORy)Qo$*(H{?(s<_2*yx`B#7bRDb6D^@{&`#ecoxzh3eGFTCRM z2syXsh}cpYArs2v1V@PRxddNE@Nj}J7x8f!CQ?XbBB78k5(*`lP%6U}LWzPekn#mm zuADEz6pFD3;otR`#=$?n=P9Kke40}@ra6TX8bYF$#W?xH7iTOW>>3yz=I<1y zQfZxf;t+p@_aSv}v+EY=~(|y*FkM7|)OROiD&hl_PPU+gF^X+B{ z%x?IKB`$r{uiQ=c2DkSrr?_rS6})yJ*xWm#2F|5F9m(julj<<*;Zh2kt(g>`v(O~} z)Qq!Nd?gvYHa3;}i=zfyHJ$FTcK*#44|cY=F!SJ?frYKL7G9<6`tOPi3bDUm+CtN3 zjD(n1_1J6a(GbRu^Y zaOTy``oS-r40_Xa-tFUg?h9X}=h>}#YAq0*-f*au_k~f#_a8aG>(wBAt9Z!#K9spq z`rc+cS*yH`SUzf?i*97R!!llf8QY+Y`d(~A(nN$kONjk+mIUqTJU{5LA*zr(S@~e6y$5VGF zKV1L3qB3D*LHEfwrUbpc@c^X;b*=+T-??S2xdkbgjqPJ_Eg< zU`~jBH8&`<+2~nQs#Xl2w#k@b^X{J!!?f*77?EaO`kWp)cmJo-US&_x5?q6GUraeS zv-yBN52<@PJbU*#MD8@W;3mGmIELvz?$XxO{39Wqb}8Lj1PKOrrNxTdg^gQ(?#!y5 zAyc0mjZ&H8fdSk0x0`Qu*r`q3ktSIi-n|gIt{jNk-%X$3$IToNa`Ji|S=2V=Y=5Su zOI1+7=E+GBN2fa8vV9nSa&Q?xc=wy4hj%*N=Xgy}E}XfmAbn9`)TW4g!PA$oe7QFA zXoErgscv&l^b8w5pU3LwzFRv-+QcqzGTz+uW%}`b(s3~dQ(mQ;emKzUHBAw;G<43X zr%OIkH}nst1xdP;IGKzKSc|{jly~~@sucUH>keA%y6(p)yB<`wb<3uMw!8SscB5i~ zv>Dc8LQ4h=qOL3nSW;(bU&*cGrxp202aWpO8?#YX-*tQFhDne1CJEXmEp0HOaWmu` zQhZi?H19!i&fBQfU2Xj=*HDe06mRNr&V1$gOBeHBj!xKDarA!3xdlT$CAWqU1t?=f zhyoO}Aw=<4PyW@DU&Mg_>dC))^8ZminFIMsq=k=jaD|Kz2!vb==LXoj z5ek_QQ{X~EDwPX(JRv5)1%zCN^LQMd5EF4QA%{=MNDKda76WPFf6r0?3*Sk`#@QS; zS1Q0HA}Lpd3vjuNizx&ITgYScIWn;BVZlrVDN$c6s6pBywOe>NQ)k)J_1P13P?t6x zmC;HcLalWQOpsZlF5TL|XLjVuXr+u$YvD^e4q)2XT;(69l1k!qR=$t-7goL@ZvsBD zNT!Q|wU73M`+~JUyr`G9wv~Sato%Y((#mH_zRjCpwjcFH(uAV{0v!P0W%zh|$kbYo zL?S*4vw*Py!+t#t%cQNrGO06khP@@D_4V$PI`|bWNE&ds*W`npYFj`?MhKI9Y1iwG zb(Xc6;ekLHygp_J3yh}LmS2+xcfuTXYmas{J-#FoSo#xAXj4Kz`3^EfL6X~7$HriqL zu5j0rW*4>TgHmVp%8E(oO8dV$u3cG$^G(!1e51ob-5FN!p33ZfTLB%*W1YL z4)$(7kG=cFllNy$JDe-r?9IMncJArBjPu(k^lZ1W!M(s{3lp#4^lNX|*}mw^3Na~o z+^J2!jp>Uf?OW4S=NHH@$v3l|MUB~SgwZIJ>RPLsw6aiM_tTxXE1oT?XwYEajCE~J zcl*NT|Lz5~R>Y0;i)2Uh1SGEEvw30NjW-kX7aZ@LJ!|Ut$%z$(7XR#;y1ZI;{+3Dqvx|1m?ah3C ze&WsWR}*FL+bt{IpeUCrE}TyAp76qbN zpg)^RTn<+#!3YtT%asX)GAWzSBQTy&&Le~(E?3Hx3%LprpU;-c*?hT_%@ZhuA`Vx= z<#J>K4Cmvdsq{TPN}5XF`v++%VM30Sz<7KS#$|K)Qe1)yczlUW#1n~dnSd(+Q|U+Z zHKf6RGtGld^@T~GH>uK1bS4!Ak#>@gcc>=VJH*|`+ufV(E$HaS>B#f-<^Rx5Vlv>H zU=*;B(pOid*S3)EgN0-((OF3G-&#oD$t<<|!Q*SJBQvm$7+5Cdna(<5ShP$|s=IE; z;@Yzk2StG=7T!?XSE+&Zlt$X}RjjbMkc$=h?Xvo`M zds>a+K5z1gvHEP!$(c`H$GFaWbv<;2e@xGuyX9*?B|bQ~;Wkmc*#%RyW6%nhAu5`=(u&<%K{jsoHeb4eWyA#gzVB5+^OCD_5S zyBa9mIp9p-v31NPbI#n49kyW0wUeE@yL)H8(uU>qm#k|yZd&Qw$hnT2XDqpS`Q^<% z=T1NB|H0C!xWcMV?&gqoyWU@NZ5Y3`vd8?z%bA0BpIUg(`1O@0Zhgk~9=|wxQM_%tX|yonD5J2tH{hry)>;4rqKeAEOFd3 zMWwS#I$-U;wL`vi%Qw}sOSVkuX7|eK(%F7#3HQ4Oy?PQh{KCVp2ABq^ZYwRiP;L`N z!lF34No82oaJ$hbt_>;dG%UEA!_1v!sc3!m@%iKXa?Nkt$P0dZ{>s*dNvSE#mkmu~ ztkTRaa(m|)ubO9R)NDxn>pm?*Md!0TKLr-uS+pY3v2fjsjXX}!RcD{Y1G}zWBV9Qw z{n3?a+iygpk<+f2=JqdryAd1i?6)dnO9xNEd-qfI8t+kr7p|SQf$y1bvS#f=kLB3A zx5nOf&u!MaIu1S?=0|*r8qny~%oo15y*p-pl3nzDSn$C%=XUP$SFTO`i!Zm4Ez6G# z^bHK!cte3jWp_S2HSg8+#GAcW(2@pccRU(VwzseU=(LSZwr3xCc4;&A z%npVL7oiI@OyTqPMNXX!-3~=K7IuxhK#!k(V;ptG=F3MC!&=X7s4Cpk{E~6jt{C~v zR+RE_dsi;Vl=6*I4;xtw?J;PV{DtP~k<4S6C!U6e^yyo-;rOuJ)ibw* zPD~0>O&j-qXye06XLu~~{>R#Ux~!zN8F%JFQz>VOTV=~`uV-GI%rwukio745G$69; zh@v%D>iDG%c(8iJ)U^fsSw~DJJY4RS*|hc8J|hoL_PP2`l1tkGo6G7D;--)5+@0fI ze|8G%pUTFo#-6d*;M73z?*5t8Df=ArgSsob+PXz=_M)?Lh3DHpJY=bw|E9ocQ+9`h z(T}#|PODzHwPN(NO%qz~a~pWIu>X*$j=vl%GiMlhbEJr_1lUZnAJ0Dn6>1XVMl+ zU6a&p-Ew8uN3I^i-rg=B-gcTh`IUNhn_kyS^qJCwTn$>^{jFoO$+o>EX~2CH39x z%9NuaZM!a4&Inp}xXE@WlllD*kMQ#PB(3a}IdZL(6>BtEvUh(MTdx}%<}ZrpA7HS-PsU>&&Nj8P<=}+FO6@wX4a6lDW=ieOh=g930kLn$UJtR&b|F5uf5S zCC3}SY?2?6-Z3b5y%+AbrGk5F{AW8pNZ^kr))QI@#_f@ z+qUe=T0QHzD09`hZ9#j@{^3*%2)nzcb?UnFE%vW0eIT*h*1UK3HJS%)OnhG0SV^+@ z2TV4g4xN#9YRRw-OACiNv@#u3Y>0Q^g^*GhvXy&u z`=F)?olOp#uUJNFIGyFUX#LKf4w-9Z!YlcY8y|L-`#BVuwu|jC>9(_fS@RTOsw=l` z^LJ|Ovah_H-cayr{xLLS_^q7y>7iE_MEfmv%)F3dT6j$Gs8M)IP+8pg3mKn$T2;Su zkuh)iHGasgYp$>NEN;th6EPAzghW7PUu(agg;T27-HQy(SWecpD2^z`%9`;JZ;x#yklXz!3qu@(7s zHzbB{7<%~h)-yE%$eHOI-CPs+DW*leB<5N6$+eJ3ROG ziWqgo2YdpbOBfjjAm%PoZnb56c{N8OVKU99Y*P(LB+6~k^<2|F>4KeNa z=)lP1yK>vKd|}#pxa{#M_4dSGaV6^cJ?^h*waTWyY^(F+XX+0z{i2xTafzmb@3^j0 zHa%!?m_7esq^0TEE}pNerag$dG+5jq__0xF-|1a*j*bknEnj+`USiqFWOlO=DO3AQ z8e}ugsLR=+_daWzZS3F^VdgZicM*R9WB<&N7hCa|^A}Z4(v0f9uIT(cR`Av7k8_>( z%TM&YF{7>5Kk_zg&8=1wi$+P0JeS@WsVyDzEVgKvZPtd5X=|PG)A#pouzQ;**{Hl9 zThP$XB#||<-5OD+tv~Y={))_Bk*O8aH@x`r|GLQN61V@_zJG1szqapR+xLIF?MtS0 z2qYo}#uKpRQUPDe=i@x79AitkQZ9jUa48`tgi=1i;}V2WM(`vYxm+${OK`aaWAiv1 zu8d2@Hoj+bk!uy-v$e>0hk)QIWC|`{Cgq9vIFAkSj&JPY+4`jHKa{%RPktbyCPDlA zsT%{N{mDda3tUrsVd5b~Mtti0%LHvtLw1C2A=957(K$RU+&etLo6Y01F*fGojl1LD z$>=yn$1>@MuuR%oeMX1b>z&3eyHj5c+7jBz_1H7TSF`VbJe|T{_eMI7arCL%x{MBt z!xkBGw|o6oQV9pcb(teA474$<^7^x#B07gVg@t=N=?LTm6ms(M#((J-9eZmj?Xq;c zO!atDSof0nrh^ArbsziuRpo`dH*$977QX23T`#fJ3cYX2+So(bd+55ZQwQeO8Q?vw zH?P6_!SA=1>~h1ZxXutb#rCy(xJY0&bnCd%eZ* zS5C5(5>HI^UP0v1%+`_k4eKiBu#lY`+dKD>()wcH)^ysojLPfoA)Eq z{gn%Jeo-bR6U(Fw`$f{WHfwmX;$XR;?Bveof)%ueyB;66`@%m8afxuU&%JXq;f}@o z_gk$V8{6fGzVx@gpAT94o%m!!PB(=@AArSRZie3&Wt6=>$6F=SBz}=}g|)A_iaLs` zze*;7oGi^37k(vHkQe381}VZi=u*O4V)l zs^i3`ZF$CdV=qSfjD8&4xqH;AJtZ5BoIHA+uI}_Yzs04sxvLI)bZUKZ*&9`M^N(0N zw~^cTZ5}+;q}7_yvB{jrs9V^&Uh{5kJ@vBuu0_?gcl)jRfReFJ5#QXQNWqLhoiORu*7u$io02}=<&?`qM;8dg=a1{_7vJYV(~%kHhK(P; zXinJO1KE!RLt1=z)-6(~w!DO_Pj=Rnt`P7FnrA5Ul6REZ51w@H$jPVCv`_R%XWOFc z2kpwQX1;#-s@D`(bGH_`jXNJ%F!|28%_~Q1*FTS6G^@1o{LYc>=bOwVldUaqC`m}Z z4-QJ!km~YR)3JGfHQirL=lNID{a>KzKCcRg)7 z6HDtjb=m6dWeZ|A`kaWq>RL_vXHiAl-^m8jzsyK}due@Xz~agUC6`w7y^qzEDW%PK z1Rbb7TC^C15mX$l+VLW;omHpP?xKAx<_yiNZ2tJ{rrYmiPYBIgCaavsE>ldkcz&#i znR6|!@O^B0J{1!wdheA_*fKBlYQg!yg^v$jJsp^CN7-^{R8GkF?3M+ymyazujds3^ zsF;1b_mK5X?ZEZ{mNnQuz{UpK=P!e)YrH@56>5LZUk3ZP4EA}-;ouTEpU)L4ggC~< zIYOC$BUErigoMjsV>pMy5pf8P1Q*I=7@IBP6AF<)#+JxLgn}>N;BsA>%J(FvCQZc& zrN3*f)&-^j=XRzqw~nz>eB_ z?7u_h!P z)~f&lJKl+#yR=T*%R?9!dl)qfm}gq}aPQga^B()288`L>CCJX_hUR3vCV+bt`7t+k zk2oAP=%BU9sW^MPxFe+pO`CN0m|*fc`ZpsfV_hH4i@jJW=vx`@EJ~ieAiB)5;EPDg z_hjjRe8e@$MZX7pFBuvqZvB8 zc(PBy%ZbM*k2haZ_K;cpW1TB`VqLJIB^5{4i)Wg>GofDT@Q!|>Ot~VK?U7*P(;(Z# zWcL0&joqJ~_&7Lqe&Do2#7g<<$E-W4**}X_{1wf=qGud4xnD;jnp9frOAKxVVVV6^PilM8sAo*g~lk;|nplfGw4f z&h_`yH|bn|Pi^a+Yc`w5#f7+>FIUJF5>7c*&9r=)7XZO$ylgxB>W4u8ll zeYyIDc+6z4L3av`9b!+ebidb+>DFi!@^v8Zs1Fv`}CWE@z+vreh3WOu(F%U@|@iD8(g<{ zj`w}`X8F2YY{RF{-NrZV)Wc>-=G^0&DQ9gv8Jmp{J)Pso+-0}mj`NXEBW_#n7_o%4 zKf2i)jg3tkzvO+RZN@lrgV$L2nk@}nux)!@NfBp6^Q_-~E2wrH;Cpehuh@%Rq3Ivp zY?`W0fb1cD?LoBt`7uMiO2&0czrU-rrCs^jC{0QWwzViDy2D7<7rxQFN7=jI<*b#M zaTl+4>OAs5={w$yr{pNy>B(QdYsGF zpvz3(#bt}P%46+*e3Ba*N= z3Xz=P3KR+%hevQZG92e}WrTz+kaPJGoI`$O^D-+!;Tv5_w5V<>cE3?E?(5A$b{^=;rAi@kh*y-54{l9#(>Bm7F6LMjomv4>ja*cvzQZ8eel>R!~r7l`b zja~ROZiv%4`mlb)(y7C1d##wqmnkvkm?`AGu&n8T6>dq!0_Zer@-a@me92G?4-;XZ zKaa?TpEaLH{I~b}LHxwas=DyTs*(W%*T#HcG;~dQHvj5ivonFBoZForO3zecTdjvY zw(ppQzkU>Q@lekTYu`9KeMsNOSy3WLRz0cjc6Fyy8=KcFhE-zVDfsEEKI@Ba`;)2enc(RXkTn~v?cYoQXdu=+> zq7f#iVyT_i>>KKS=5;sf%2#&XUPgYnfBUq_@>LUW%1(srp4PyEC$@FRUe?ccZ@*~c z#D1H%P_g>`?kpUVRle)$yM4TcOM=(;dzAU4Vv1Q@2^Dx@NrLdat)Ft$X12_+JqoX6+$N$2u=Ed5!dO1K!CFO{$f1z#qRu`xLp z;|d5K!RJZ%B90IPjcQN|;3bm!LjUmvCJJUFgqS8!Yfz(!aaX9+DH63@nNU-R@(GkU zLx?;+p$D@~5z5xR=WVEANY_{Mf&!W}Cak7H*<>nI=A%L>FB%IWtO#yn0*_E@BvAa2 z0yP3D6m+W9>H8HO6aqz0MzjV)#V{;P=DSv@a2*x0J2dTYFJ zVMg4R)lZ(!e^z{VasQYuTStu6Fh*M*HNRfedO(Z5e2<%h>e3e8YgWf7;gt8qdNCIq z(sCSUZL%SV_Sa`7ws!~0?W485OWK-XTyxpB|IQGnIKRYaYLy2_ywxTP&eNMjY zcY@PwQ{nI%{U#iqw>)94_UVUKv4al8>`Zz(Bh_~jmWKGvx(sd=zG2An3X}6pcV7DF zqr!Nv3uV3=`>V<#+Yh@r2dbb64h)J-Ueu!EnPgRX(e_d46K5JX+py4L_wJwtFST|H z+AiGoI4frcg)+mwTPK$Q`)9VvlL`_SoLD`iqTU(7*dF&vsv|Es7-t6Um_|Js9msBd z!sDe}5!R-U?VRMYwwmQW6{g*C($8ZFo2G4d`><*2)K>V)iEY*ne>`pGxDCl2HFowa z)A$M}O^bGmlShPjZ0~n$%p`ZW6Stm^?9x#F{+Ps)p}`+44_!9A@AEFz?G_Fk6MUew zxbFJM@pi%Im$iyNA4IXKpC$F?eX6tL=(TohpNEdMA2oADy{;khjqFbovp<%<@O!!M ze7^&g>g|+imc_f{ZiL@f#!t0*@N(nLt?xg4Xik>%cu&02z zxs$xwWE{0>d-WQz#hypeez z!})F7O*f{S4e%s^INw}4djFQHeRs!CbT%)W!VIh1??}nE!6gmzqnj2Mv|KrLmi=4r zz$<|opKD{e_Y>9AT{n+)b6*nMuKR=Sp^BaZJfiLAOE(`m9Oh*aym40XqsMNy>J2%3 z`_S-%%N-A#++Fv^i?^Sw1NN24MIU$_d+$2D#_t|?1seLyjT`xjW?BX1I)^8$-?Yhp zxpvfcA6^JwT-ngUw!^C_<|S_GPbogWg+8ctiOJ?pJj(a9tT}a2zcUX1u-HfX z4RIX*Y311URrl^n`p%xcOYGR4nb>l;)j;cLmw!5$lw|GdIQFsY?Jc+GG^Gs9@6szn zx%J3t*2Szn*0-in-(GiJvnT7+u>FtCdIJnC*vDI~8Qt_<$CybK!#YK0uDp_-l3nTl zvd5`Ly>~hvT%Q-0m$|falkA+k%wgFFjV>SV?X`axPIK$msNh(tutnaA`P2@jk*@Bv zEqS)@*h4?w?>oqQ*Om+ftKA}A7_3z@F1~C-^GuPtz5sd+5#76&T?JgKWt4w_6te< z`)|{HmpnUq>BT*dqU>g^HtkVY9vU!n-uuEHuh%x&`?}`lbDBQ+N^rpZPhUP zHjaDqaMg{K=ZD(2dboR7dYYw|&xxzX7mgnbJiO>`Ud*O9o!r=6p;oCTUTP?%+C!%Y z$zu-`%r+twA=F?bRU4>LM1G)~No66#^kX38Y!sbDXrLsovq^7le4;|rmj;!9$(pKU z4P+|RBJI&7EXY5sOSe!c^r)7|l}Q?SDAaMa(LWT9He@ZwDh8Z4LRDlkiv>a`MX4s@ z2#qFDtx_oC2m`#Y^j+ZyMWby=c&n?ct3mMsg`w)NIjW*G))j|^0;{_B`590UnbhZi z6BDYjG7(u^70TX|1(BirFx1neK@CT;q%755|JA|%y5jurr4p5Dz{~=!~F}GE0PUc{sUPO#kvHP|`$BC?rX7TC%1q zRK(OI#3$Ai0A8mj2prd;V75I%1yr&IGFi_ViXlTI&6*?>742X-kToz_D41;t<&GU4 zSwOl5x^`ExmNCq7y7I-J3r4fPs+$YwISDZg<4A-uj0<0>=Su}_zJe>~;{uL=%jXH8 zz_T+oq%+A7?Y-lnRCGvZz|lA{NgAh=L2*z($6cn1k55WaYLx`ZC9uWmF@s|q3T8JT z;kH7-Y$%hw5;PAZU`oXzzkVDuRrlElFHQ0f>e z4}(o$s7ef$fuS8hwsi%pO;8p2R65+2ET;`+jTumgmFo7RYp8GySvZ!2JVl!*Q`A@| zsd~)en5x4!pMq?V;cFMQzaeEpmK!!kXeKGL*%VTEDP&#jA-W>az-?q*W~e_*iUaWf z0|4*=@Sx52?hB<_rD~--nn+ZswKb)Xm*_zQ!W8J+Ko~4BkQ4xt`coi{07zPA z-;n=FIH>?9?Wb@WlW>M~^ZB2IlV+GuehR7yIqu*z09vH@3`|nWVl{*o#2h$%qs})V zi+IBv0UHR_J-q}#b$Nr(g45xxzoxbXj5C7!K;h!*Y$$SHolPet$5>xbc@za9WsPd4 zAjE*p`kOO0s5+a1`ck2^a5W{CN|gqk6Q6jUfR zUCpSfHbIuCnn~$JMNCE{6){miDq?D*sE9Fwijahgm^3N;kDwwZH5x96p(4g`sDca< z1R_J${qB7+^#rN*po%%m(Xs0Q=%Az`rXx$In~P2LI$Ey3g3$j~fB=%grx>`KneN}y z&2`5^V*v(INR3f7lV*ad8Ff$4P511Gj_Wy`dB#}t^ ze5Ohb!vY2V1fDP}gRp)dPX>cd2Vn%81aN^#@H_lZO3Y^w0Fflk0_s=1ZHKCHW3L%? z5|;73DZ%W2P<1{PnW7YBf>f32&hg-4&PXdubdT3WH`ASLE+z-AJ&t*B$Uh$Tts?oi z{Hq@kW{t3aLDgSzF^L_CYy(g|23=D#4^wIw)A)z%sFT*;X2$ObGaJ-A2!$EgH>%{s z1Wyg2PA1d_|3a$Q=x~&xVD=e=&>@7-bA%{I5Mo?4Lg*N%uH&#fp;u<75Mp|rhBIfu ztUCw0!w4}}&=G>#?q={Lciofllc1%lGMA)I90~J=JV{P?Y6vZqov*QdA$R~A9GmMv zMy9BWl!#l(4=2H{Hc=-fBq$T2!MLWwT>yuq1f?v_GhQW6()mm<5y5-_8yp* z1z_3%<|Hjv0FtKACVsw!EKW%zfRp!I9ve)0@D`${OcJHkXp)E;|HNPb!V!oMu`>$b zO4 zyK6emsV;*b<*>U9^VDfD$3J_6B8*snPzn`wp~DAhezmxm>L=cu`(@qJo29XoJb*g@W0@hM?F z^-w|p#LxzGvh?StQs8_r+k-UAEKx8!TJKZQz=dE{(h&MUL+B$7p-(h~s%QvR1Il!r zze1%WM57}_rz2!U*9qV=8Ul{}|JeHy_%^EJ|5?e0*0FQnKqALL5{Mn!u^lIbBexS` zCm{*pXn!C}Yg>-M9_+$^!HVy|pMBN<5@Ol=9!ycm3IUMs4E#~m4 z9-?D8EQ;21lZY4!62fC1`$0xi0Frdh<-GPV6HNSGfp35 zm^%yh5+=dFRyCV&A3{WbC8BE-qOA(iwF=QU6{71DHqb%w(YF+WGlHHkCb~%>da;=3 z+X~Um3ehbJqzL|(9{P?#v|V9hLboY8r{As+-Kh}Wr4Ze%5Z$8?-K!AYrx4w*kn(^+ z^j(GM4u$AJh3E$g(L)N+!wS(46`~(0MBi74epO8LQ-$aeh3IDr(W45{6ACGhDMT+6 z6aBiFpq~j#GEXT)Pb)<4c!_p+iQe@RZ6>1kyhO_j$TyV8Qwv6#flD1O^|&-Z4rdan zg^hq_;c^&}Z|G#A!->>QN8qg^afZoCg^nUpYuSJ`mq;BokBIpa=R>S92?eJu0E&gs z4~y~BCR~=_vJ{u2iG1HJ#I&+UEndb1ou~y*mgBMlmzDhXYW%SVm*cQXRY3G*{Bbgo z+8YM+j6y0stB~4zD*jC1(v8aolwl*F({T9;E~n#ihCa0P{=-WuZNi;@0(ujd_i%a3 zi?N639AG#XFR+tXEDMmrMks0p=A!N2O?sBQnq9~yGa6ndg44>4Y${t6B0)Cc zo6So$1-VpgBb}ilT~PQN_%|g)knExyR8<7OcuBl`zzX9Uq8>v<+1YT2}cN1v37zknX+6p66346UfX4H?mJWBep z1)|85WPi$|t}1o$i{xOR3brY;OQ8c@>c3oUQ|Lbhb}958Y}21}{RjKg&NhXu2fNj3 zn+p1GSL{*6ut&N6>tmDJi5%=u=s(z?(0_)`bFxQ`p_oe?Oj0%{&Q1OGwMv=!X)ke@ z#te|eF~fAAY*Nu2&8Yr1x-~~7Gn5T_Ct&fuC3b8m8IA@-o7C1El`YYtwTm$eh350D zT`ZWT+e}p_+nqt8%L&&T*mX0zUc;`pvg^HYM#9$CRivN}70eq&xg0>d6mv#4U*vMB z^p{-nIir%}d=d7kIbVcbiaDdzHnp2C!d4Y+(+u-OMVKe5P=oz6N%X7gNDL)h*Y3!r8}}Gtj~*I&u0{I3a?z!l^2s4asyTk8GysN=rIV5(VM3 z$|Vz4i*V|$m>k6JEK?`yLZoX(c>D0bkG^Am(%q!*m>)*4L;FqNS@fJ6Ka8p8pyP7! z!??6V;e&C|cWmLjUJqP&F+bO+51w>e!Scbc{#lnT7~9+`|e^D&q zpRXlSt+AB9Y4z$Aftddr7#WUC%R-(hPR80ne>qK{qHM)U_3Q>&%DAHb z53g<-{*!-W-lglLtZVJenj8SBg5LyT4Ui^Lx^k5&>((r|t;9&1M4-C^TZf3~VeA3n zo5t?sFt#e)!C@@m-_2pfS>4BB#93i$2tJ6jGJcEbtOxjgki3V(2xhyT!w4e0jl&35 zGwx&e*uDHdLI(|;*lzM5zdu~SKLVlgdJ));G^3mdkTl*$6x;p$x7cK6yo2p3KjQbX z67ndACkXE#4&3v{90Tr!8^{;I&9Ej5jndsa+EMzhmFwg))m>%f$?P2ff#5nV zkwh545X()d^^$l(cMw7qNCxx0yT&Gm~6oU3HwT(=wxZuL=*8OMfgLw1}C zN!U%?TVSs;3;UUS{||h85-#ZlKNozQiG|Im&diGjMQIksY^*T0t}4+54%HzG_njy% z=P_m$W^*jeOf)C&*z==o-n^RYC<~r7*3s;EbvN;8p*^1#_cNdF0qztT%No$gI1%hy z7LF!Uf%Zh8vnm+t1RJYMj5{{0oPKz>M|2<<1FG&g*f*>Wm{Cw<&#ndi%&vQUSS?z= z&R|Fm+Hj*8Cy{kvz3+2u1nkPdn#mB@O@nK(J-7PyCT@j>FJ9dpPNg)f>51Xgc!a@L zO?8Jm+riga8TLE-7*^Vav6~pyXV0+e7l>hXt9FAcF8w^utv<)Ys%p=rC0{fy9hB0C zU01yNz`hZ6PmHJ~_Pjc1ujAF@V_mDeS~ZKA%1i+M2qwUwjj^s&SF7fVW$)R?vU`GM z2idc1=@*D)nGrC!Jr-+^Xn}Y*>55%%-^Z?df?Z4P*|qG8#;$66d%Pp%ic@df$EkaQ zQ_Ji*b?_IBQ+><`sA|=+x&ihLse6P`2ir61kS`jesvA>o9ai`58&dbgkUGSkQ-^-h zICY3_tF8}+w3sUsV4v%1kMQeIdww1EMdQ~&?a5Ri6%M-M)d%;Dt$Si@9cIs~!@p>} zI!Yf~yOLTW7>lN~sJltlK8Ncb;o9N$Tsz{6#=+&aphTgUF@+*%S2Mq*td(<}zZ3in)d z?fs_7tZ%}?_ADcp&0ZFs_*vrGvG!a$Zg1jRHafNif?8`Vw$3TY7QE|gYYm2~qME)3 z3ai29Pc36LtO7Bqi_Wn+_wM7^0Sl-dXV0xE)hl06NT0~>}%wvgmHiKh^ zuJwsUG=6Ok#C;8j&zV!qOtxxGH^Y;6m{YaS$UuCMEhDQ3?@a@7PFy@j+mK2Gl2z?m zDjsOpl5tH-uTy}TGreHpX}BMB<98oV@8-ezV0)e}`oi+`;7B;ywV^81wN9(jLb_)S ztZcb&;oxEHVAvjZ?kFN56l6ie!JArZsxr4jLXlGxzf5+AQ^AhPKrm9NMN^5e=K9c2 zWLjew!kzJmc50W_<^H!uQn`?}9tVvg*&6cK)$zn^cUpY>pEJrfCa$h)_(h^ZEg#w_k zfv!jj8SFqf98WdyjvUDo?On!?nMAI*J9uGm>rM_A5YY|}BLQDIKZza*_}=38QLno> zj0Al5a2N^r9_KI;@Zl&Ce9%2O0~sGQ#9bUl0=}m>4AwJX6yJcs76vUOvNOtz1bpxC z-y#9uy&N8iv2ZN@(E4wV}jMA{?=aB!Nh<_c%|ohh%|<>5e3Te;_^a9y>*Imk!Xx zNajf&lew!WWTw;X9S0G#`AB=Qw0L}%gcvx(HB zGNmRHAv$>b$42C{Q&oEk6^3ig(KM)LR@swXn zrUI>zaI!-SO-pDvsXH{SE1F6m?OzD$s4yIjccqvC*BS_&6ppWNxWkOz!%6ktoKLFv zQA$g6hNFQ9OmGMga_T`C5cpSeCe9Sa!0KTK$%9?Ib|<~3ONW|`GHVt>0>f~0eIODJ z-PvzN#rTBcqNrE$qOzma*^#KT&7u}$FY0KssJs)F%x_+?zF|kdl~vD?eC=68J!i4g zZn7Reg*?I58sd;)bO@_u0Z!T)X4bMWdo3qeYq@5@3O^W&C5+U{6~j8;RVLDFJIO=r zzni1BjN0C$kOI9Y_A6?QF|LGF*sOn{S@ojqRj;;IeL>Uw73&)+=SRX?H06&cw6^dD ze+U!xKq?%IRzc)@;NTNJZ}lrX6wvz$vHw>NBlbU+hO#!0*(^meTNGz+n-SKwS#tEk zyZf!GRvtDBT8x6uFgwwgy`W>Q1r5iOTF^hY>7Icvtq-NGHA|~zFYP${(k@)J;_-ef zE>7S!IKgaK)zpQGS>BTD9fz2Vy+ z@^rt|1U+HZou;XR8Vxf0qcl@ZirZp|?m!}xyJ>LOfYu{z1C*MTD05Q@dn@3nek&}} zXQSbfx*C=M#DK9+nOV-kZpt}XW}G<8tyI$A9Zq%lTLU3~G7+^7uua2!?7wPYwEr>h3G@o=GFbQuv+yy7&Ngc{#H`s+ zH#I9aJ1Ef>tZSTAtxI@EEM6H2cZO4k*X#zRHI!AsEch@t1W&YL>iIrn%P7jD5TPV6jEzH z1oV+YKKR?1H+U4h!T-hW|KaisnE7Lc)RIpWVomxf|L##p-Q0`I@g7oZD-}}bQ~~F7 zyj`u3I8F z=ZIJ|vazxwkO*}L5?Uo2pJ4-FT`b3;(TCv{TZJfW+2aQDDn( zUeX`Kc^MxpE0djpNCc~H=7L}%(2c*Lk+52Z55BFZb@lf4nhUE~5RL{?ZhvO1BZuRu z%FaNvJ)%L~LY1Dymmi@@ujVk87BA*7mKMLxVJt0vm%~_2Jdwj#PQ0GO?5r*hV;OK0 zhs7nn1O1?zId)lC;$x>n+br=ZIHwEebLG3l_dCAChowGYiI1JqVqN0HGGL}9KAgXW zv$upLKIUfrwnECy3ehbJ(RUQnEoPYEb(FK56g$f`B_-v!5X+KS0>rW(&f3C~9~{#E@{)O?V=b|h z@ZcWDF_OJ?{BIl^jlc6dHo8AgFlxba#d2JvfWFnZvj!K-Vxisf8@V2;$(9IrddUa* z!P=F+PH4^x=seuJfJohhKmivgA060tiBQ$g^2)Z;CF7B`C9Ab$%AX9Uv?P2n1^Ckv zY;v`E#AZ4Rfrl;2V`iy`Q1!DUD#A&0%5RA1w?unN5|vClzOqQ7vKu8)G0s*UAW6({ zMpHgvTYI}CT7(Bel|Hix?)3CuY*9bg#dv#{}lB7>#3tAixG}k!@2Hzb=VlS~u$YQV%uWi#4RxR&@+V z6KvJpsv!qbBr}|{l~2aEy;CHaC>nB^zew_9JeWw@pY~yjdg89h zEIX1t2UkxnGOGx#9tF|d+|{F8qY!OXNQ∓Oe1oD@3BJCxgr?b`wj(y@MmscZ1Bb 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 F{u{AbvvvRg literal 0 HcmV?d00001 diff --git a/MikroMaster/20260221/20260221130011-Config.rsc b/MikroMaster/20260221/20260221130011-Config.rsc new file mode 100644 index 0000000..6ada27f --- /dev/null +++ b/MikroMaster/20260221/20260221130011-Config.rsc @@ -0,0 +1,3955 @@ +# 2026-02-21 13:00:08 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260224/20260224050012-Binary.backup b/MikroMaster/20260224/20260224050012-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ad99eae3d535d4727ba6d4b1626c3c631523942b GIT binary patch literal 289014 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 e({^zWKhRPkF(*r~KmI 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­d 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260224/20260224050012-Config.rsc b/MikroMaster/20260224/20260224050012-Config.rsc new file mode 100644 index 0000000..a62358e --- /dev/null +++ b/MikroMaster/20260224/20260224050012-Config.rsc @@ -0,0 +1,3956 @@ +# 2026-02-24 05:00:08 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260225/20260225004202-Binary.backup b/MikroMaster/20260225/20260225004202-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..5ea77f17bba871af82a56160a2df76ee5b80deb7 GIT binary patch literal 289014 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260225/20260225012726-Binary.backup b/MikroMaster/20260225/20260225012726-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..75e9c5dac0396b697a3a37efc20202c350b95540 GIT binary patch literal 289014 zcmeFa2Uru`voL;AfFyt*ARxXX%`UK;o`?kz5D`Sch6PhL5GlbVG#i4VSg~P6#g1ab z-o=8wcSS+5V(*Ft{?BX@#P0iDfA`-1_qh+x?#Z%ecV^DaoS8YZJ6Wq17QTt5BV&Y+ zG9f{wiZw$BQ4m5ckZyxx3lzjQMJS7kSdNY}SdNZ|DX5A`F++%nn5fDbu@G{m%cErp zG=z{kLF0uGf~L9tCiGfuqgrivtl=7yT5WH#9mHm#DhfP`W?t(Dz4i~I+CPkI|1bee zWO0&sr9vVjWQr&QW=-@!!LbPnVwgs9|JpeN~Rwj{= z)TyejuC~$N1CBN*h)qFN3^;Fus`T9uQmf)r@d+xm*6?6l-wBR53S!d{$^-m=@^~6T zOgRYykS$8BN=(4?1H{$e4M6AV+dy-}Q=kK1fBrN=h^t4Hju6ENMvlajiV!2d$_RQg zCR3=o;iSNDstJjl_q{$;=<`J1$Fg=Gqhz&GO8{zs)E5t;L8q!}6L^rGX~?H25@Tce zx(+0l)Ieqg9j?hpK4Q4!*6L#{mB?Ze6JSs@ggP!tJwT78yZ%_4eStbr`t!hrhBow$ z)Sm~=^Vhc-2%$KAn~4xg)wc_&2)UymwlPBa2-pPB)6o!~!L%ds0+fukL~J~v1)2HI z#XxXoy_$<@3T;A^{z?k6A~^{$SdNZxQ{W^6SHk1S-wb#x3n8YBDMC!+x&|o7Q7H=0 z(F<+>u+Wl|lPysddHk)%0F8e77&^eUhVj*7G@5AgF&a&DWDVYWdD0Pz99I(n_D2X9 z!<|h#k#`2dB4?B2>7?2Vn6azXBAtr@Dh`}&HNC7{hV5fpz z0_+BYYQfnYE(l|yhEN;S*)07NKw#7LZBS=Z^li9)s=n<-MQ9cZVq22J_zyx97l`bDm{fzhW70sMT5D1@S|ZL#PADXav05hp#Tg;oxz4ocM*AZ= z%-B-zZQ@c{ueR&l6{(G8HhAKfba40KHU%!o2_f84YwPBEXUB!Spz5Zgenxjlb~Td7 zuVRt_pymiM zikdQEme(mW(9=u`IpdJfw0c`?X|k-BINCIHpc`@hEOzU`UAyVihAI}Ccq`qaDs<2! zeM+3{uxeqr-I$!lW~bB+01ZQ@rU~`b?*a4`ML^M$qXYnr=xRj*L{9ynaF|A)0ZJY5 zdf$qTEj=#`C>Zn@J;TaI?duv+?&UDhV{@@dOYt=dIX>ZI43z;Rl>Ib z5Hn60qgF*qB{9I^2D$iMsetQZ33;Set&EBy)HVHJl7J14Occbn0?Wt(W)X=@OT@Zs z2(4BbA4Ogd8{EfmG}9RYjJgO>O>4m<`+Y+L<}S5L6Q`0BaA%nMa`jJuV=f9}8zGc$ zgltg|+XNxfut5lsstXJp!<>VVIjJqHtE)}Eyp~OB=IZKdW5cx!1+F`%z>N*p>UAYp zEQ~YngmPeZBML&z?MXQ$C7}^1sU)Y>WqQ>?2uY)4s(6KG6cJCTC8Tu)+dw@Aa2%+c z6G?3YCJjv7fHYWYKy%PQKs!r>C{_p|3%I{ILX7v-K#nSMdM1C6ldc^?&M*efh@4gQ z;!m;{&@Wo0)g-92o^cXoykVri9^oShG0kCw4Hs+FNeOC|!f^cxJ@jx~fr8j`5TYa@ zgeD?{CLu%_2M}h%ZZbkl>u6|AhuuuQ-kb$8(2b&lem49^4QF1_&|sMIN5Yv=u*-zq z7}$*mj7B5mY_5ovXrev!piP6*Q(-p+c4J|e1-n$()uupgw-n)zJ$%1OGV#BRcC?$rf6qv7%?C+JuBj#lRI; z^wfak6}^RQurrMG&W0m^MtW5Mh;IBzuC*umTesQPYTMOn*Q?cbuGMy`)oxU)4Lt8E zQzgc03AM&a5-)d(RmLf`8YhKH?W9#JC9&kBs4)i&O%cLD@^k{|470QjZF4=^?qm-T z>9~Ygji*8xt0iF6ewUBH3#`>sCw;%efMDa09hHh&KAx)%R`Teor*>`MPNx-alO{uz zGwFjW6EuX(6BKE!`?S*E2ac`u_W^A~8WSXC!1X01$xKZQN+dK|cU63BDiA_dm)56 zq9C@xY9rk!avT}}P~akfQX#otZ^!FKi-|rv*HzBn^SVJ)zknl>beI7;uqx~8p@Cz4 zJ?VfX)Y=62jEY90j8~}OH*7w&jy|6miUgku;Ew>J3juu6(j@&i&~>EzlJiS#E%AAj zK}SS>Z6vhTKMjtpbrT?o0!)BFFeW@_1VcZr;0VHKl768x%vX9f1v3{!Wjy7HO1S|O z7#!H(Xs^4sGyKL`h=wSgvLgm8WC3_&M_H_rh}TA{60}NHyv7Y7^s2hLx~=XG=yi2< zwNT%FQ(axn*0=K!LTx`&m;rr&@7jRcu)^ZA!y`L(59rt&2EbhRD5X3S zfECv24Ns}*T^CEi@S5I1-ace!hM_aNRzHBq!0pbaZp}J%4GRzU4)WFYh*oK|@sc$ zGmB(7I!ft=U*!L2hCbb3765$#Q>i6FFxMa$0H)p*hY5i}GAab6YR3k?5D120*qJ@M zh6ehFcI_TgmmJ=j$P|+bx2}zBEFsYlHWb}+U+VD#`FNpke?SPm(YM)DgevrH9u=WV zeVb4He7%5*&|Cfa)>MRE>)Y*Woeu~16%18`PDCAi5bS${eOqHL78k*Q#qto%pU2h2XoR0#5s7M}+EtRQe}g2Dn5KF`syzzeys zn+rQq{S1ZH5QLnqaWPjY7AnL%iC9R82|_Fp%As$k?1)KE@?ZQ>lw*F5a{X^m9)yZz zzeKqQIJ!Im_PZ!s;bH|QmJ?zHE*9Zpxfmx%jGvW0pJML#=8s|=_H&Fse1ma$iCpRq`*e#>7HQED(qZnV8EF3;870XhiZOpV1Y1tf{0517-IoSlsVx z?3ok;e=|UVe1m=IBiS#pX9kA^;NC)^u;cHdj&z7RnmS}nto) z9AlX4zQMSAMFaV-#+en~HLO!W2XCj}$J>g;TPT*{Vj(W(iNrjG4sFKX^xl!L|0vp> zevURw>))WQ9Wv^dQfv~W4AUxQG5>C?IYKe65X;$OoCPZR6CYJMbXcv}MoW8)I{7H*M^>ehrRQm?)^b5Uy ziFN~jNvtF#)!mzoxhJS%-3P0ZBw8X?;_e;)Z>BE=A!dttY_XIOa};7+H+@x6LwC2c z{q#q9zVFZJ0A}hpbZEKj$uC9SqN8tEV0hOMcOEws^Y8fE28%T=mUG2?Is7T)VuB~; ziby6n9~bxOPQahFSo-}Od9cgBLB4N6^e+XT5lYD8l7*R60d zCT0u7I1g+Ykw7fb2{>w6&wJ*I+j{Lr`D2E8(0A-sCbhu)O5VuYfrUsw9+uh}aZTncEfHd}U}Wi#mIUDtl`j4e39$vf$P7Vj zp`P3P&s^S(g2*MM&#?tYP?%r16VC&K7z4A1cgL<_?!n!CNGfElxjsM?4nYQMTr3od zC4^Wm7xOVOM2CK&2*dn}Fwz>r4Ac{bSwk3z4e1FZ1;TLjgt4kk znBZR!hFo%Yk0s(s!W{0CbouxmJz-=*F;6NM@WpZ==y$2&CxrRtT9Poj+ui%4md=2m z%LxR@zL67)qOHHw1IEgbXjMG%yHcXRoJ6zpl*e@%iT=FG>-;sUOnQyJg8<++cusEn zhuu|rkTSdniKCNx#W^m&?2oH;$M30iqZ%|Jw)r)hOj!N>BBV%q@?S<3(eDnVPNP3d z?B^Ic=+z%Uk74(f2+M0k_>x|P>(q!aglqL8EC&(J(~EFgZ4ut_jR=!*)7lJM8l-;d zumI%NSV>xMKN3~_zsVuhb^2!gfLum^#TE!b7wBWja4bMUY~8}OEkYDKgvj;Z2D(-`Nj*i{x>4L+^nH49|XbE-4PCg-ItoUoBAW1_>CeXs>s7DHpjwpx? zX5e z0Rx9xskyL9Tn8aor-xO3CJnfMYD)WauwqEnN95iqVYU-HrIHCn0}*2MDcVJig}fB2 zu4JH{5u-avi`I2N14IK-k*Q-$STbkAq8Ov98t7c5%i5%o%T$Cmno#3T?oQp~39Ta# zkd%~1)+IAC23Xfb+hL_8Mk$x6;tSK-lS^BYDsXt}_mND_{rdACME_3^Tbi8VS2}*pUe!3DAP|!^DL6 zggC=uAgnjR21iSMrVWIGX$VnZq!JUN)DrpUECyJof(?#!bZcOcriGYfUXCuO4ps?a zGbAE|92gcIVI9rz?C$zBXdsmpLJX`0f`kSpT&&|`7<*@P-$b=4f$$7cX=JKoSg`~S zfD|56-O2~ax{ylM3L(b%!}FA|Kp(4$a+k=+RZB=lhYeCiU;}tY>Dz#-p$%+oxCYoc zPk+ruDx4?NwMi^l2tf`2fIud1gRsEL`+b^DT7ktGkkw}n99l;|Smc^E2rd;eO?0^( zunZ56CA*T#ww7RQ=~8%NRZ%s|#>R0(oJyTK>OTPmnUPHS9VqB>r6%S-0t1-?NhTx! z5r0MrIw6Zz{YOTF%zUK%4jqiuM4U=X`?>X7zkdvfogPW%D87!h$2Wi0Tpj8Ml-*7GsQ8EhaA@_M><8-&nRkQao| zO-L!xC%eHqZyKc8>GQZM^orskLTHZu`lkpXi9RXl8A9kIC=C62aizWuYr%~{>mY>>H z30h<16Wk^gXOALh2*}4t1A&5-O((ek=VLN1Th5l_WWJa(K1v%+kZRT=p3p)Dj~POc zg9xgTVvG=DU1c++2||puc?*;i5n?=hXuBRJ5s+Y*QN0ooV)h<_5W@(eqQ;DK`C*e_Gez5IAXf;lR4qjZq=dwk79uK!b2+OCB{A4~o_LW)w_|ry%Ngtwc#&U*Kb+T)uv&4QAS0NlV;hMrlQ=!Lymh^A19u- z%Dm-gN%3)YzUuyDQbxbEcRM61Ef_H>yZ5+oR^871O!}OP{>$rM+Fs#8Uvj>){qFYD`oz4v zp8l@F$FbXvf2g*x5yjou9X%Y5M~Fja@nh~hJW+YKf5{5>;Yz2Xhf9{8ZEh608{6(P zt@LWQ4<$F+hV~VQ@5EcpyCiUOP99+&m-Qw zdbUHv_|U05u-!^bbM~Otrn}?BL91N19n11~dd4;IjEm^7FJ&pKpu?qsX5+N71rBXz zlvJ+pZBlM=aQ34xtKzENmpwA0mnhmi9DOh)y&}1QH?@vY54Vl8Mr~&|TBvEFKsjZj zwVv*iOd}>v|2Uwl#X9={SI5dZJ*HM`-llcPcD!+a=((vIeOc}S9WG7e=O{0jBLzKg8RIt=SQj+ApZcRC!r9^UV1x1pD39<0lnzN_9#>*;wI^GZdZgoB@C*u}2c{&f2G z^{-B4#HKVWq7T2cqqF$>YLq%UZiC6&wAX2EiY_ptee71$dDyvUa;Zo#|G~wf%C)Pa z#!h*mx^V8m9%}!~<~fSCwC8?nefoOrtuF7qsqdO$(GJNY#(y*(AKqt@t?A*%{rqm? z2SUf8W+m)veTLD@omGuSMQ1A$h9tKAa657ryKUQdiapOeJj}e=_%(CTj7kY{??i{f zhVct4BBIMO&xH8YDR_CUXXToE%{Ss#{t?Z4b5-Qo$KQv3@9OQco%M@T96acuV`2x5 z9U#AB=X(!3^eX-xZ<>+={V_e&fXl9;p z)%KO<>V+uBD`W6c#s#5m>RAwBbD4NHYbo{A{;qCG+KdH5?=5_}x65F^f5Nskz500V z+q4ZYF08q`w0J}2xuxQD7Hx94FT9>~2@w~#$!u=*J|7ZTHFjR^C0E&{vAcIR2;M(@ z@SAK?)3Va5MYuz`RXe|NM58mt9nUnp=>AN4J}W*e!o2PRnV)pd;PIv#8nOB~*zL;C zUv;3;)hd4kfB)>o#{$dlY&}_?wYu$@!cHxx)(?(+W@9Ff+qEETz4f8110UH$JDo|> zEGStVm%CKiOD_I#>?`Oh6@WGA6D%z5YvKZ-x$Cz4RHuHifG|KVc@`J z<0A|08;0AOj!bP8m)&H`Cf~?Tm!6JWc4kh>Li>p6{qB3tPid4|7%5YZJr(<&Sw7^( zzH@D5-G&^xBXzj8`HkzOR$g28`V<#%cne>)SYW1_{$bpHK{zepPQTE45!?E*oUiWk<AW1`V$n+P)Vr9uF|)6oo;MR?H-2P zVm9!DWo`b2635Lj7M!P9(?W4J=4fZm=HWP7h~aE5hDF$!v-udC&Bt&yhbM}_TH?*I zrn>8YspGK>ic4*vC`O2uL9sws28Bhrtw$+%Ik5^o}v4BY*l(HNR8nR=W1I6~9v9rr)&*x?H%j4%!J~F72+BWV! zIfs7xddC-0M>OYh#$=S0xb(Tywof;k$bRK--IrG{*v&aN+sW$G_3CrG@xa)VPj1&w zz9v=}-`8er8aTb5`o-p?{E4&Z%%$Ffe$~v6qJ5jEi0ZXX7Ms~Ln=!O_%-i8F?1qk= z;5hE%TpEvfpR@Jme782rhP|+hevPY|y6WFWe`o@cVPStWIhB{#u3EnX?$jaAyjI z-V|$$xf*_B)X{eOq;NIP_E37n!ffiHQb&1WE#a

28=y#;=*d8ZLICn_(=BVQd_g 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260225/20260225012726-Config.rsc b/MikroMaster/20260225/20260225012726-Config.rsc new file mode 100644 index 0000000..a61b1d7 --- /dev/null +++ b/MikroMaster/20260225/20260225012726-Config.rsc @@ -0,0 +1,3956 @@ +# 2026-02-25 01:27:13 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260225/20260225120026-Binary.backup b/MikroMaster/20260225/20260225120026-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a47b5f0e079be4db150f74262666c271cbd12032 GIT binary patch literal 289014 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 pnr= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260225/20260225150026-Binary.backup b/MikroMaster/20260225/20260225150026-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..4cf20f03e7d9f04f3a5726b2ed7be22c6f6e7ec8 GIT binary patch literal 289184 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 Qdf~@Eo>@qy*|F1q18S)NT>t<8 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260225/20260225150026-Config.rsc b/MikroMaster/20260225/20260225150026-Config.rsc new file mode 100644 index 0000000..2118bf4 --- /dev/null +++ b/MikroMaster/20260225/20260225150026-Config.rsc @@ -0,0 +1,3959 @@ +# 2026-02-25 15:00:12 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + disabled=yes dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina \ + log-prefix=VPN-all new-routing-mark=To-VPN src-address=10.30.30.0/24 \ + src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260226/20260226084004-Binary.backup b/MikroMaster/20260226/20260226084004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..b65de0ed359112f223642f9c9c8744023a6ea595 GIT binary patch literal 289184 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

Rf9H4J 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

Uu=J_Jn%xiyPgVg}dyz~#e| zTvi{bS^+^2pY{&X;MkzKwUA^UyjgW{W@}`~@kJ#}P9fTu zib@`76y=nBG&lf{9b>W(imD7oof%pAQIXSAt~kWV+_i*bmL=02CqjG=YK(2krALd42LyVUKka$TD6~^dVPxaT-rX4;Niyab9PYnAE%0CgiND za&_Dxc)9`_S1>LZBh_4ql5F#Zprjya!dW=wGpIBRNr|X?U9tumuDZZgV@l*r1-9P9 zPD$~Rer_k=1=8P3E(}-_ zwS`V)n^$x4sU;2p5Z;_*AexHj*;+^-oWitnV_TXe|B+5oVg(JhB$X$nR4Rutl_95J zMue9b3C4nI;y5*ujw@%^Q8LX8SR?=SOhLzSr7A!!orKA+}>n~AMqLj65x*p_i(7c z#QOVB1;@!jSH~0yq{HGIZ-mP@0*>#nugUGET)I>y-k zFhCfec6C8;B@XoTW{pg!cA5eiC>gztF?MPYl3Jcatl@wN+03L?dm?I(El}JfqKvR` zwilX<3HuluJN`H`wrI`28t zZpOEhH;|gBOpT(rwC?YlK73GR(GY}29Zv?bCY1rr+fOGTgxz$^0Hu%#B8_H7woMT= zTZrVPyl$?lxJ7Sc7&u4e)gQ&ZX1z*_)Ba9$8sR)K;Zej?fa|#*1~KcyJqiPiu0s$< zeiF`LI&Zh&u-mVqkhF2G$&1-CZ!}6kcM^W?2tpI#3{aB?HP()?^5xZqkQM1flQ;?jZK z*fB!#mz_|@*Kno+tY9NcL*Fy(OudF7KOcqd7Wy_@@$m%&PeIkgWmN%KOSKvoz9)1H zW5HXZLx)0;faxi)7^VBQnDv1}sUG~<+YbtdkvI;AWoukwhkykFwlu=+#yE$Int>iJEznMhf^Qc+ zC<7;(vR=zC`7OV`QVOGaxx=z;n_4c*4dfC#7RIrU^RTp=ACFDboVsm9S6jNSpm=$QrF9WNw=y?Q4LwvULmXZU6-Z)T2R_v!X&e z#9v;_+z>Yt`Slf-G+mUk-$AuweH2AWbO7!3iS@~hm?)=^#Z<9}73`Ef{Ut`{jzbxi z&!B+tW=o#mAYP#uR&;$_EK$etBiLvM#StY@1M3s9lVWyHJ&dYc5aS*i;pu0FC+R%k zOmG#xy~eV)qK-hT`Uar)2g)NvR!Eblq7f_RgUtnp!?v`L0Le@j@8?T!6PXOEjdqPs z9#d?rI5E?`L|xNK_N-$OARovvFOHYPsK(r5JYMvo5t7@)N(YZ0lQps1<#}cVg_7$4 zfy1;H)WYU|3V?+JY3bAxtw!k8XgZDSbSBcHd+E#ucbjsghM52?i{j{XVY0@9#7{71 z=fOu4nA^E#f$YhanBhU~CO<%=uZ;8%)gt}CX*!V9HQmjj);{bSo>&oc_CIq-dBntxh?ef&Ag2>sdlw?(PSi~iexy77~ z=z05Yo*ob@>DWi4sKyG57yVX$7M?0^Ytu6`H?v#$N++7}0$$tITblu05Jrx!Mby~J zVnu~0v1YV8G`%?G1>QW5x>SZNQ(lm2&G7}!_P1-@@S`NV^+aK8Z_+HxiPZ;aP3aY5 z-turmU5z15L@*D1NO)g`b@_@!odp9IWC~Ru5dmPul#&wcIT5VjIIZMIoacovod~Ha zEL%0!H^_>6+1>ppDUO5C$UyNUVbF?rOjkk@!l*3O-z|i4NOL)Gqwue;*G@2>gzcmh z`Sk(o&#+O$D>VQx_>9q%W*IM7VO27#s6{Fe%6ZJTWfzAbSBya%RH^&(bR%QKTXEU! z0QTK42<8LsUAaI{ohsD^OD>xgi|(AwOZWom?HZVWbM|V)#i7R!i7IaQqL`39?~-CC zbXM6ow=p&r2IB1PfhdB;C>ozZ2yQ}hp(Au$Y)Q-gJw+|sird8qOrA!9=AuWnQ9Qlb zEPIUtItqzR%D>oHW_8bR@Y<;bsz@St#p?x~>0muMayX9f8a{MC_X zx-H^Jh-~sNeqA)QZiVFwi&ZtTy)sc)H+IG|9P()?lOWnq_6 z6SxdGBE3e8-Ktku=mm#L13EdVDvRq?(rlHou>I}VmDTVnWrfvtKk&S5GyK^JVKW?A z6gI;bz-D;8Z8O}ODhrEY`VH)b_k2Cw#~3-e_ChgafdsNhc9#24+FYmy!WtbehbjQJ zio@lAG3IMmwF9U9;^}ZQ%lf$K6)CwVPPcihhY2+-Witi#wWEosx?swr>hYrLf)9&AI}*_gI!h}m=}J=oq-V2e z;5M_+N*Tb@`wH+@HN-gHY4xzyNgc*$E6uiNNK;6cRAue3lEqS6S|P0W!U}4=u&tTL z;ij&-U91)+f|@ZAC?kd+z*M9q6;yrlPiBF*9YCjau;qbZNvyK0il+R)-|r>-xZmV6 ziPwZD2pC^3ubE)Om|50yQUa~Nl{MX9e>j{cW4nZ9o$Y{?LT(S3?2|EVEXem3a(8%s z(k1B-PmZipr- z{y<*L(-}>Lj7gjF=S5^PtE7}-$HO$wPmAMDHKo#9B`8AwVO*pG!rRoM6xcc@=6R6J zBsLdVRx1*N7z-9qD|vso9KiaKp9)$@|5w$(JP}~}!ko~w0GgN6DaIplC|p;B=!C+X zo+hjbeni7CAE za*>qP$imWkqd>t~T^6=c6DOgMEzV~SLwBJAi3eCnVT_gpfoGn;D%(ZG+67ZZpI!>2 zJ8e)L&RfILW1O)QAsca)S{&dZ55QGBHJ4haEW{*>YfNQxh)4BH#n3}Di@Py!fA|)Euw7t8jpnof{bOjP2NY;1>jknDb5or)PJ1^ z%TuSK&*NCLV9oP8{0+23#H(}QaRz9mC8)cHWn?N@L@o%VoVDFOwiKc}QV|EcC`W)?cqbDS6QnRXbuop;>+bu2gfJFxc9ROSn zWTiKdB7^FsWy>~HiB7Xput3CGSI&_-DLv}XKLP@c8y)bZbMOdeIM476IGupN3=~H< z-NKZeAe)pi6=aj;usyikL7nM2>5M1Rh)fpono^&^2~FMj$J7wiwdM0EZdeYX#}YtGwMkfVOpbd;A4zIo+^<}1_- z+5{M9ZqskYbDR#|XHvYVndwezfErt?wf@Q5e$c0T>9HqG^>m6sGh(w4nyZwZ}OO)R4_6bOjoH4s6_LEDX%1el9f7( zflx@BgHzbbop>!6yV6b&K~T^hO5(j)tjNgXuo{pF7CuqR)P;Z`!dTp^8C+>WRx`0@ zCv_vaeQop*V{6tLh+>5fMTv0U#tKL<<>;*{V@s}Vf<28|`HjkAy|kxd`?bA&V6>aO z4Fr>V%%5xcRpFh>V<=;wv4U#MYpTcXRJCE4era2f4WyK9+L{1y^@J$D*2z;zY#G_j za8u{pDYMQ5%@)akpxL5L$CSxq?KTo>JLK!MxG@9Du4xx@af1@JTE|@DK`H!N;1^O- zVLwi?f+3O)M$uOQn#H{?=m1l#+b@H9sB)~MLO2*A>zLc6cnN+o1Zb_bSHmFjs>vEE z-zRd~b=!q=s%Ff+*^6qJGRCqLvFQkzLEFt^wDh-!O+GoZg)wvJvT8e-B3GQNS{iTY zKec&B#dN%u{H{Z0Gx$1t%@rn$R4#O`Ad%@BwkrJ8d@jPh7{oeQ12hyRG$AsRg{og* zqCn-hu&*GM+Tva}XuwB)4GaPlWHB&_OXY|ZdEg8|uJa#z9L3{)CeEE$VDnx&#n^Jji$ zm}8-hVTR4yweHZttSxY{OM`2yPO`BmsKrUd8a$X!7RFDqg35@*Bn;Y3+#)y2hRSS~ z{8q=^iJSKAKXCBS&6Bs>dU)!{(POtw&m2E-`yF>a{{`M$wZ`l73;w-}jb;$G?u+82 zy|jFK<%Q+S(D06tox4VNi|9pyF47QXxz%B74sEhtnWhM>NBYVUdO#iMrL-z*-&d$1 zg8b5h7W={Kch=gblv`4HNu$An+f7+`?3!3eggmtf0CG!{7b;Sv z4Z|`IDvs$xdU3DY@^Iq-asD`SeZ)_NweQ^UQ_-4Aer-Gl;;dSG6TMUh@T`am*9hl* z=toqewF-bgUuLnu6yu{S%@(WaN#$Fo!y}8`S0+MD*pUjYn4;6T*B-nGLYaj}3W%vf zFv}!ect{r)YDM}m=494aX4hFfJ|xDgQNs0RvT-#riDueJab5})TT`D5YCK4!Dy$8( zO6NWnah&w-Jt$KUR}k@fQ-%;d#Bb#*1A@?gFfOY%eI*SE1+|`0KRV|L znrYGqB1|$X+{#xpDRDKIp301hBM6XXdV!Vdh3lvn1d-)lTE=jaX>*)JsTQA4Q#y&= z;F#~wS&GmK6}8K#d-)_Aqd`6xm2*E33V?&bp~SYvL86lC1zc9CbVhq;=RCTigX=}aZF;Zm2pGiTno>Ey z*j_eTw$v|L{m8pbMV2z#wM%d!`3NW?&vtY#wM&d@wLvBZgA&KvSZ{AHd2A~eSP?P? zu@=1A3Q~z-19ZMK}&A=PI~~$m0{WR6Ig) zx=1;V;E|!GEPJ44bs^<%CrW_@?bte?7{!hSaS=*Wavx|^W}`UEAi`y=7O9!)S6nCR zp|0pOcxKOWQROLwgdd9)dod@-^ogjU(FzbyNd=ImTJadViufI5SjB0DrdMTxXB77@ z2H`RtK}F!{IWOjhs^a*P1uWG`2kC?tjI$J#)@8z* z-PWVd42pcOd!oM7BJ3QN=e?aJHL`>wlOADIF~S?9_((DkIHX`#U>yJ965r`w=FL^r zJqH!KsA0(33l?F^=0kZCwR={wqBYFAbz`)Gae+V(6p(?n+OYhx$zw8BOijjSz~xJR zmCNoB3@*f|=97GXD?^6NXhD#fBBJ7kwQ-j&`8YSbQpM*OL&^_}9_8_pbGwCMYq4Ko zhx=xIiX$(SGOlvzp)C_p!v(-ZgG;XRG|3SHcE4Kt9&$WgIQF_%Nm1!wSBwW79MRbf zHEkhrF7B$U@E!lJX0QC)Qw&8ejK9u78_i&fIfNEwhFk6&Nxf){aU@%U0#ARh`mwK^SY>IOUxaUoI(7ME!n4_7uk@E3s3lK zAo7P^>*?N>XqOFsh}LPZf|ZXW=+OzU6Oe_ALQ@u-6$?fQJo0dx|kquznvMX9F3P(IPhcSU+A6$T=|Co2}sGqQk= zou;KlMjA}>R^RvV^|ClMHv@nHqoFMLUhxdq?Yw?{iO8ZaPW(vIMEPw@`r$Y0@kDi45f?`CQoSeK?#abDW|m zBl0l!da2v*Md$=bHDPs=Ju1`_(PT}k2UwqbSDy$MazAMy_tVUKKSD$FpDMWNi!g{@ zy6`x2sfaTB;?6Uv$s7*n1+B6bjx(1ku**mtY_&2#$CcL=na~xaK~X(w1X7w_B^?gu z_XvTnadu^*lo#m+!44x@L_YU|J5!th+Y>CIX@)Z-$)kH}b(LqGFbpe31vZ=HRWrt> zn;FO_Vw|AtHk6f3*IcWtR`jb3Nm)n}3a+Y;&&b<4y-e*J($*MoSNcyJdl3 z`=$?5$Rhz?IbjKrAm}NkE{k!j8BCa1y5M~zwApRmU*ds+Z*2d@sAG#EaF@C=Xw^Qk zw6Y(@O+#zGXGn2j`l6yW7SF$BNGe?!4m{@_LuNp$`-SwFH&m8RbJA{RcWkCQ>v|nT zNHJF#rK=fF-!5VpfWrO|*IEKX1P8T1Y?o7$mPIAzZl{1*`pA^AR7q@Yi=>h`V)I8v*QQYf#i?judIgK1q^3&|M zF_lQMrX^jvcLd6f+kj-%Iaj4<-A~1@$BMpC9V|8s}Q*jS15CxfWDxOwj zw6U(5n-P{c@!R5J1t5=6h}qoULOHhyn9Rlt+^g}ZSoe9OHr{sz`dSA)F)Pfnv(}EF z3O#1J8c2Zv@gT`f-HwuSb23>)$6MDPnB18i6LR*JK^mCOB^cT=+OMk0Nc*kQpe~@J zv|pRMT}0uFcq@#3ge2`{(lDz{j7i9viy#DoCYuA)sczD;g7mZQ64aLO?&Qq$A+dpX zXC>!CAMqH5m8&Nxp(-3hib3gKjwEl=#-k*KQStE59EImc#%Ih#qc&6>oTr%c2_JL? z4`YiASCxuGH~tF|?0Ed%I1E_dnbgoZ3u~C}PG&CN(7cu9K(-nW;*oRVAmVunw=B*2 zF)-=SxbYN({K>Gicye}3HRU^*-k$7ID~}(X?cME0<?$8JVVb z`owA;jYv?gN%^pcPI>{<(IF`vtJ_V55A?ZrWd)mi_sMc`_w04Bhsf1T*Y2=pwzbU- zEKU$twjF4-+Vn=}=oH$cy4w+zNykHLPO=vWI7M;pCTSgjrL-C~HD@IkIVDov7WE}z z1cGbOKQ!=+{xRhx2wA6{*|gz988y^gnNkhXlfTqtKphwxy3nT2!hXCU>J6jxm8JSE z2q`m>B3icWY04B&6?U+l5!I=2dn9B{G&MU<)x&mRc~&S=8UZaRoTIFz+PPXEr7}YK z6qr*Jq1P%3r$nk;X>{#b6?{wi4`%yy)oq3JUVt`9LjsVYU9V+T{cg(OFYWVcLkbH2 zr0_?sV1^(NU^CnJZu#iJpnvWy6QS3n;;9kP9H$c5J5m#ZxF>!V0jUi~i#|NUm$B>? zdtq`9k1valhhen!8l_AzlHO93ql`ky}B=tHMnW-{LcT$ICQi<6BUx?ymu;>=Y%jD>Y)n$@o z*PAPs2(&f-*)|p3hd9p=Cb)xqbq}vDvd3Q9Si(`dbq%mYI3dW;m1^~po_hoXkT7&>d$zZ=#Dn)cUAn0E<%79O2AFSxef>RB;d% zhw3mHOL}Hc{R$DSd8d#W+^MY$4Oz+cqsTxw@eCfj;-tsX1a!-7Xx&^qL$mDG@72Bgm{4Nw`^3sOls&6jF*HQWmD_ zYlRKJx+2cT=}S`uC1jFqgvDc|V2Uk{0g%sQR`ct1E-oY$-7RgHxvktT%vninqMz&R zrja&XQVT@0NR>UJql;u3i|#M(b;XTF>il5$mRUkzay|&@7LPSFW&qbb!AY6oE33Im zJaUPxcUJI7tX02g*Yw6}Xj`|wD1RGDF(Rx+o!H{H3!O#Mber6)s`SJDRlzQuMV z4grs|GIlEEY9f=f9W{zEUHV8ID)U-Wik_2ftQrPOSokE77sR;ZX1rM&ffl^LJjNA#KY(Vzez>}Y){2yH6BwF+o6sTZIPkK- z)$vdxo^r*Sm4tC_K60A zurLomHNqw*^{`yQ2+Ny@GRk(8cXZ6Bx#v~z=%J-Zm?I}a#q=T}2YwemqzM0Lb*Y&-F$YKcVXE)ouVouw3 zT`(i6!#0S=w8olKkAxE4j!Ctv&`M)|P7KAWQ{YB-L6eE98a3)Ej5U9W(Pr8*t~gLg zPpLzYze5IKILELz?MSKVhr@6&W(|LlTQ&==a^t2TYX%Y%kleLfLXdaXryLXF1wQ8m z2xGjxAb)S~XG&W(`v%k+p+gzFF&?>xL+NB(?Jz%eQGm4uEKDJ|8UY#rEOIux^tq>o zhSe%mj;Jw~nK9C%!-kkUKDrGN9H)ypZn2>oc(pM|5Vq?up#ddPLqR$H%!Rd;0Y!GQ z!NZLl^LsvdyKxoGgS-**@zm6sYI7Plz4)cpV*q6|TEQGvw%&1M5o~Ic52~;@Qf zRKA+nq$gL7&|}Sq?5sY@nHDn2ws~LMk9ckR=u9_LR6bJ5Tpprg!#Ffk>VEBx~p!%Mz`+M-M4k z%am}g+dq}EF`EDz2f2rv$gCh6su%Z9r3`XLmg<09#yVcyTabWY#~WuZZrhOlkNLT} zuHZ@bSXdYI?*X_@5w?c)tfhmYuT&^Vt<|ON<7h_e{_xmKUQb`kV=u&;_p7`}_ny~9 z8)6~M%#OQ_DMZ=%GM8$U8jb1QFI!ze57Dset`MdMo4D&nXhq`c=Cw;%5wf87f(D9i z5stXfK2)EGMQ+xwVu_lb5zOfCREfGzAK)ofVP@%vy?U`}m0OXVoHB`Kl1*6)<#ty# z0G!aet$kgs5ZY?JwGNn7>i{$0Nwc&U&SE7$&fLs(fV5mlVWoiC3b9=d5z*FGN*ry{ z6`~++8NR<6*7^ra>4Qypq;G(=370ZI%0Zpltf6=GA)1`p!s|37n;~wtGDQ)vk=&+M z$3X;p!|$}NZk#guQNG8Cg9rmoU#Ok(7x>s2Yt$k8kJQ&ncq5<=8ns(}vmm04|+>3clSoMIAX1T6d;1EC( z3hX;DwIR4A6K0Zm0Sg;79;v#OB}X!k;F1n-a(npt9Bk}{D@O)X9>FlhEndXH9d07_ zO@bY12!3pwZ(j0G;y=<`s?^ zdn0z|R^tMq3M91<`RK=}9auI**&XKC{`o+Q>Ap2<4(c^w1;h|a(bDvm?u}fET0To^ zgWVbcl0_&k7#x}mR25Lt-m=uIbyKAcQ@<_lHIx3N3UMc%)TSOD)hHFFQUj5ek zK;6ZfnSh$!3JW-|;c8~#gy)9=s<9>@<{oQca$>lFf-lpA-)`YvN2w4L#iUjYmw43h zRt8|-4p_vCn8=01msyN@V0uOKOe(Bw>O{C1+O$kDl10ugxzY-XXfDO`>H%p_1*ZZD zaLn4?_>U2LqN0?{lXb5q@h+fEnZBe4K{4p!&dkN0%x$&fg_a+ z=gQ`gCPkuAj_Yh`H7@L+BIn&nNBD9~Tqp#xxK%yK93atVWFlGz%ShRlNz{^rl5r}Y zCM~75960SKM+0&HFDqDo!FU4=GIfr=!%#e!a$Wz@J^v&p)fcJMl*euy&O8f|45rtLAeDu!PRi7kUr>?tR3v-SjhFo z&L1E$s;|2^b?Er912W{LsO4C=%qpT<(2OcgSzYN(r9700^>dStVB@K1`y%T&W$tIL z@0xh7)U}du*E7nPW+ahDy=PA^Whl<7TVyM2Pd~yLP3SA&^I8d-+9MfC);cJXQ2ViP z*#r3n6Cc7=^`j)Bp(uCtFa5=u0u6 zt*-14HM9fw1INL~?2gb{WW+YoQW*wGOscAh^zsZ0@~i$gUUVwp9UfImv_}@xw9sIP z7*u;vNopIO7%zmRTXbzjod%LfaLsGB?t9w21n?= zHNy|Nf=r%O5*Haj@R2{b6a*%GQc7&H9Yec!?B2O+X!i)HZwujRFQ|ph{k-9I9B#q| z_h~r9%#wpn1b!k?)A9Fmk(MtrEfwHo+SJ6I;%_nTQMc)I*=RDW3n3`(2gNz_sfjyT zg|@;n;Hm$UFo?Mft(*X8Ux8pFEU%$ffm-9jTO3;~vqBi*5q~0tRh&^d4#ZWj#Sezj zG@n0k+Vq+jrea9tjAGj+r6$sjhOT-NOjH17#4g8OrIWL#3Vr?eUwhpRXU?8FrBoZs z_VOPf803yT;UGt~l+TzYX`sL@o%BNdrQ|XtcN;3y|Dt3|hVMbNy z?Ze_EjMxLry{qqjY#Q7z_OwL!v_7?5qg?$ox5}XSsY!0i5B&XJ!ZGA#60d0oU{;p> zY9rL~V`X0~k*(k)P9NZxQZQ61jblp1uWV{9tk73Iw9Kcc|a|9`4UnLj|cCQa-1qbULws0QCTcMjkBTf80i|c~(5c&>i^h z8mLqTDg(mVwCypGrX=3`= z^u+T|9653L#GwPn_8mWZ`+hF{t0j!L#WYPIhDxWg(qk}Y`i&2~ZJtTJOm z3O&hk&1OfgVa9Z%VpnJ$Y93F`$r{%o*y}1~1n&k*?iMU*FRCM+L@P`yk~#4#Xl^0Kl)YeW zgsOn*1%XV{J3U@0i^-_NR;!{?$;HA+S(kM#3;V)WNDgQdnR6Nz=Is1&?X(_CWk{ee z8%n()i7VT6EgLoiIyKFbXiw>+=(a-;zoBsX>&jtfc_QaSi$4h!sqo|n!(nA~Y06(h z^^c|N2~Gh@IH#tNwXa}SX{tNu+!|ie3@8U+PG>4LLzYjGV7j^Ax0G?ou6{%y^$6=| zKR_Mg=}40)9l>Y-*5;9Mq4y(RMR1-m?7|jgeUjrf4&uBXp^aWr+0@V?F}>fXY$@XA z)?F%UeSv7i_C%A1HN%BVtJPIRU+sp{Y;?0%I=swj$} zq@}3cF{VMm{;zQmEFrimwcRSlyE;Q4L9V*#-wefph1IYT8(r2GYd$7vd1B04GD^<* zkDworgAmI{FpnAlDejT14pA#B>J-h?!z$wslYyWEr=V*FLX=w78N%US)}PK1FQ&Ap zToyw?$zAwqlwi$XAW;ry5q2rY5;}XDy%bD2L7;zg(a=L0wdLY-P6i`{y7AZ4Vvc;m zl)Z{@>OQrjRavn`5>O1cZo)lx5hTRa)Z+1Gs~+nCptXqX4522MPyo)9qX)XSezsuMd|rn`e;MyaHfZJ9|xrpZB6rrioL2|>iAO4r?~AxcE_$F63+qG@fsnOX zDkd+N@D%oJ)@5&8polOM`D7*##in<1+U|~2|kOGE9C{*<9o{PlgSV&Q3gi$xQ zykcgE$WHUE-bj*V%h>J1JY3RffEa2IsXCRx%G4Z~;KO`iFt#bSkdnL;+Fn+UZD`wAf=d{d!)P%ke@KvndjVW^+lV&O z@Dm<+4HgC}sJpl_dx6J1wns&#E^WV3E-!S=w6Ijk#-u2jbAn3uq7Z1}Y_Yz1S`tBU zr%clu8E4X}K`PjercIZqR|=StNu6dLb#71Lpn6qeAw;2lEwT_ubT&FY_CZ#D2xYdZg{0L5-ErD@H2L(J2zPmDQK0iPbv0lc;mJOC2xOj~-J3G5O zXm@5jGrN*(90GZfBj8+e2?>y3xIp+F?g)f~gusPA96u1kh447Y!9n2uOMpKK&m$o} zNcUBB_e{_1$`*#(547ukR##P5S65e8*McJG>ErbnXcrqNkcPE=?xMk}j4npcn%;%b-$G>pRCe=(7VT1zI z2vZ_JATE{|E6?cJKsg;l<4vH5%CR&91lDdZ`I|YlUBMi`k0+LFEhY zo=QO7KvyhpF<`D9E!>ZZZ4N2Uf{}u01AKX-EKIT5NAVhDVK%9}RSp^pX)j!^&fu!F zQc6tZa-#DcKWr`+T^){h@jK3XuM)vR^S-Eu35OJ*&~iQuEeKGG(uWme5*hbKo+1wb zwjqEAX$Gl#s8%`-)rzeivW>1#8*GO0iAH7I!N@VwAlae{ZkmYk=4Nlah?awpgR-E% z!~y<<`AqMvZZy@g@N8xQY5a8wm0!B1@TE(4M-&!jul9+t=XjM$z;x~}ddt#btZhE5 zo9(Q|?9U;jhRQI0H(iLm#puT-7zmPZX-|ctSPQnzFChc65CC~K>yBN%pRt>R)eLn> zF?*Jo8N}C_xP0g7GXdK!X0dqZ$j+}zARaeI} z_b?z~#0{aB!$}*b%~Fvs1V*5JqLd61Q^2>67hiSe$~G6UlHLUNcm;+WwvFR4i6 z!>!iLfyvmmw)MCJEHjz`4k%Xm z%EiE9b}+Co9gHpcRAj5<%thtZV9jclV*OeANF}a*)O9tPDEVhWD1#2&P9L^3BS8`M zA`{~gq;~k2ru7d8)0~IbXIl<~jlGxOLNmk@4f5*P`fM}cgMt{O=4|M)-rK9pL=(oy zRY*niVcDX?5{@@H6CF%699&{@q#Xvvf@>I`t~G_DxHS{Ucu1@@hgY#sr*N(diUL(W z^`iH-Ev&&jGvQDMWp!by`CB};gjG3HF_hAa0|E87=5Dp0$M1skpDf#Pu{Q9mCg|tl z@0HkPfUwM>u*SUQnzsc5Jv20%Ob!lp$`t|89k|7B=!OvI?%+UB-k^&bZ)ykJkl9`f zKyhBwMAe9CYm$o!fFrpD#o+KTn4M~%TOfv<=E51YfH`Whp<}D1I(Z6^R7+v0^>9&G zbE#UQM<&@sfiPQ|OK&m=8mQFCBsGX%R+OVG#w%m1O#B0nt~XrGt|$<*m$PhKO7V+q zboGJ^bfV-%Xd_H&VIpR)rm?TR?LT-q2K9<6aFC~v{{k<(Zs$`vO!(7hpu0$TZ~h@r z0(>$Z03R~n*l~A45gh{Z*=(52KwzN_yi+{mIA+7Yfz_-Ea|j_k^#tZ|Up%vNESC#E zX6|4P0kdh@pFP4MKAXzb^V)G08~p7{IK5z6nT9G}f(_Y~e4aVoW2$B;ig%V_%axVP zvMY@%G*Tg4?Et5FdVvtFKj2+Xxlk1E;to(Vvf{mIRB3Ctgm_C-s62fgCRUXUkJOpA zp4W}OSfW>Q%9#r^)$NNVd!>@*I7(jYi=}#{qHc`!#oBr$M=#>5BkdBJ(do%M?{s)} z*QJr6t0Cb^I-8||(Z<*vPPPDxdHfCq)yBL1CYBiRU*(CkFK2kdwG~>LN=KG1H8Jfvs$>+k>_q#b>9vV;&)Rf< zSGu2FvX#L4qu3=GFM&Xj;Z(YNZF(TVotEI7#vI4z&slc=V7j|2lwG!j%uX*;Rf?LC zRcycSp0;#%hmdb)WpK}vGv$MevWNA;A&-aO!N$;y9d2&O|jjA-+T99x_ijW%;~n~=k>Iw`~6|&il${v z%HS|26iKBAd@AHMilyOHx~D(ge)K#8wM>z93i3qO0UJ+0pZyK0W>Eet%5( z6tQmPWzDE)Mbi?2Y)kk1XaNs5yMz(KSa;p+=>Z>*qGIPY*|Z^qlC0{sS`?dFo9_2n zh8DH8Y<0Qz^gz3ZGZ0DwLfX?kK3{=+mEo-@SvSUHOGBV2|Ms+}yVrV+fXkcENL#wc zCrZi80CQOd(-47eOAq)6;sG=QT;&tpQFX^LZJa(poWXQ=%In)vZL?SmRP7O}mh_@F zDO-x|LSP*^r>FuH{T=B6pUGKS_!5gkkKO5ke!oZB=D2Qv`x-V$vE-UYzAQA~(;WcC zQtYv!CX7O$yklvaT97kJv1pnio>S?5VKlDCq5VVY9-rFGO)JcTLV<$rYVcHWWm2YZ zB#BdO5Cj6)0rs}=ASYC&vGtS+wGkz+<1JD={_%G#D7Ww|3a_l~klNucYQTOv3WqvM zk>5@c8C_1a%Za2wzy9>VfQRcE93QUGJ(TYDiBqdWG9kAKJ#-I?qAfg8YBb-Iin4po z;+Cz6g@b`rjjm<~*$V~y=wLU5k!1YGdr_Z(tr}CLaD{?>ny|fKS`EAPPPdRO4YX>$ zY5`yr-SC19Ybb`qYld53Y;6*thGlhlZF-;^<}{EzxRi$D-FS;>4MoBMA1BsBVELqJ zfmJz>U&|RKu*{1sgAL9%U~wdb^hxd}mExC=(8}jItHG!t;BXXtj)3FDxw?35L! zHZ`BNvSn58>3yruShGEy-f{k?_FTC4(_Cj~ic>k`NPDE{DT#hKr934ugkPxy{YuiW z6#Z(WU+wg(gMM|=FK-pYPxO>jH%;%MU$phq0R7h>eznoWHk#PR5-9*}!?cLE=CNkm zDPSG6P6w^iLF;tTI-Rsg7cJ67i*(Tsf)DRvka+MBZN zH&14paxQ?^J42gBA*NK3Ue)3^5y4q(72G{2Rx~N9SbD3g6}7yrl;F|&VAKw=!vNl^ z`dV8q7AFTy!_ZXNxO=@ZIUfWjfb;bZ*i}X+4V5N)_K^Viz({D<30m(lDd6@Q^V^$E zB{ssU@o<=GjD%+mD)2Ji3}e{>Hoi@+<&Q}KjMl8_kO_cLOjA7Y(@Dd%;%ZUX3>UQ} zdL<@{BZMjed(}Z}vImfGVmgzCTChz+-(B_e6V5{)l?-BrCMv-~xPwH5+*=N}S$N#- zYkPqkFJ+oLlLYbm=BT7F2ahVf11JzIHLAoY3`hkZJU|f30V7_GdZ$Zm?4>(CO3G<$ zB0?Zpu9ih(2?;_<8m=W#3V~UghaHBiO_{RmJ*faFZ{;fL?4Yi}0x(*}0)2+bM#t=q zDgR*X5H%+?eu5SlBsN!z2aCF@84h(F+aa%x7PX32r0<8>8g)7LY_&5{9qMIFup5BJ zij^n2JA*z4fL$sW0k@k>5w#*-ZH-1eH4SOY)OdhloLFnxKq2v|MdSZSKT&+R*8g2H-(G-REDEd&J@=7*y z{~NJwM#fr=)2!Of;|tCuEYZgd#Oq*y?P4C+DVNhMk$Ao=IXJ^2 zN@-zuTi)m0CNF?N^M^5f3aYp{%8t%prW_rxjbR1Tx$r6A*y1{G_0yPHep#Pzzo_p z28G~Ii_drjf#xrnIR$fEDqH-N*T3u-hSC?7qxx_Ghd(PIX#(;pimgLv4#!t8Jmg~_YAUlSAh<)I zkEZfS^K|}F=JLnSpR@5(7}Yr^ba?;f-h34Wp0(@S&Ns8n$xVdSvUS7tSe%;G4^o^B zx+zvsYL&YA3WplonpW@KuBMV zV+P%eaAV(xKg(dI1G_0R12~h8tCiv&YSA1pV^7pgly~P#^6F+lu+P|x2k>FR0#WUd z>Zr-_k-mRmcsm}lC^XBF_2>(5+(Xwx4-=sryHP%8=p^DG)#8QK`zg)~bb5o#*`g^~8f6jIatJ%gl!Z_cSOa~N8+Yq%Vj`7U zv1qtGjJg9bNPBxhmj<1pj|RMiV3e??fQkT4HcC+%*CfT(Xr;jF5B_2Z9k+NPM-J1# z$jk^9+N9t`S1SDYih$ex5bCp9WdMwxn1=^L{30+r<;iN5!LrTY?ZOfwk^`k6gBIcM z6tQgnPf+aMr(<9*U0|wfVSr-x_6iMY%)>KpmsVY1X3+0o2Y-uYxdfI+7arj*tE%QW zxpGm0eFX;Ef@GXHEs|-&yLeQ2&~uXRviLv1&?tl%H+UrB23T;1<(VEg@k}o68pu@R zGRjWgRbc1m%SKWsk?H*ravY&xtb&!tDQwUto%JQlwB33#MO;G27$Nm@w|!lYkg104 zB|;j=E<);G8;g)UA&twz)pE5GHA1B2%Ytvi0~2z>GgPdChZh4tKp`q$xI|ecQScSE#qw9Re0(FWhl7V#3{JLDy zkpm_0d@O26RZDT;fl9@Z9E_^OWL2O6Hp;4#YDOjqe^G1CLf02~r%1@<*T6WWwJd*> zOf~l}EO9pWXu-5W8>D&{4NU|vqy8tndLKhjLt3GDj?NWsjFHOTDwY&GUxtlflhfQH zS@cOYKq{RxMpi02n(c3Ifcwg};W2gaY>4Z#P^U_V}zR6#?G zpo3CYb2M95ieQ~UG-kD;UV;EOeeh@$K6H_FDw1izqjL`YZncVvZh%pMU(o{}i+d$scgC zIc(X1*D2sJhD<5jL9MT$j$pY?XSg$xz{}eu$}WIEklP~P03R{F@kEx?G^S0;_?Yvj zWAs@J6E?p&ll_yvrV$E zoL2Rk$27?G*i1N}ST-x0R{1(-;PXUPshq*F1>X1Li?nO1S=IZg$l ze@0Rp%s7w-@OO|KQ@{S|j~sr;;x z|5BLq*z&>-rC}UkOBCSo`4O8Gg{vPtmFgi{wu-TksrWR8^Ok4}-A3@VgrDZK+RW@2 zZJq_g1){WuX-|)^MZ@|G^MqNzDT3f6d`#mCb+xU#Heb-bd|M7zi*N<;LEuXyDo+P{ z)e!Y}X7XW#qiP>m<`wa*J)jH#`yN6e@Hjl+_eq&ZPzvDVmk28c+*_DdW9vS&JPcva zgTA{p&#bG1p#_=>42tFmLe-x_|HE1W9x>ql=Kbml2qHyB2wdb0zD=oZGei{zNl6z+ zk7OTANx%q|u35~@VBzQT$P01d8DQxYX70;j9m9DaN`_}t_dLV~O~ciVvL?(J9^l*; z9J5zIgbqBH)L4LBNLA%x5! zgj@rE2qATZkn36cQ}dwANa`pu)exCaNIkT?fRKhc4TLmAz<3f_NJwMb=(_$?N9U@^ zLg%*3hMu$5Z`w7~bM88&XYIzsSv_56ZX7D*Hm2Od#1^e*EYUV%jrRA=1(S;HD5$A` z2q8&;D{&mavH&2r9R=Wv0O*kjxo*ofvFK}CS2eb}%E#{c)e|>N zd`w=Vj{o!L{^r?}|M9Yu<~8p7>UYoo?4Pf=_oe@pzW%IpoH}1(F z_(IDkSA2VG@2!_ynVTQ^&7H3w`BMC%Z~pDJjW_PR^{nw1tmFgrSHJq$1AlkH7k~Kt z9o=7j;=H@-&-=+YzxOxy-Cfe3KdtLK|FuT?O!Kwt9(nxA%a8uq<>M`%|I;1&_SSVj z{a;@`rY-t!544QTpOTCXx7vR=(0=?mx1>6oZuw@mxwC!c_qQhs`cI#`;^7B3ZhG<9 z%W~gRHqN>5_5A}4m+m7gF8k!)zjO20Tc7&j4SUbI^7hWL2j98q-txBn{}Q|B)m6jF zrJIg={-=-p?eA~gmppIp4cE*O3A2n6rp_bG9FZ{RjZO@eclGF6ZkM`tuzh23 z^4u+xo3?H{r&P(T+?J^%&)uEeaP~Qtwf>wMgh?gZfiU$MMI9?!n(fmDc&3Urb0XyR z_YN3eyKCkB@2$Tg_T<;)rm%-yZq+HJ{vMymQl= zH#%?K_IdL1oEIOzVeU67``;_Q@X+$djwdg~{`z(E;upVlWB2Vt$vqeS`rX%WTyye| z-o9i1wokSF`ttvM!GHejz;Dd{zwG$qbIWeb-u(~5-~96syZB zecN@nE#CCzWJNGAA73x;g7wUe6;?Oo<;LsyK7(Zw10b9-&NOp{g*d9aY3Vg z@mnjNePYi^UH5&b@#~W-)_!g(Gk(@zoHNHS{^O<3-CHhPGIV>^c;LCZ$h)6@ciq(s zmYw9he%ljW5q0nL6Gy#w^9c_1 z?6_8a^2cvK^;`1B&Bs5yq2-}d?pgBJJuQ!@iH|-lzqb2l$F7;MA9&`k9=h}BegA&* z)~}2nxcr}=?;hK%AK3q`fj7=y_sf%SGM_ERPP9*R=1omDe(CYQx_Ix~%dWmsZ_~bV z)45;x)G?#E^iwyI6>r?R`|pmu&s<+iXw3C^vrgpA&SJmXIXar_*wsCeTY2Wn zfy}1y_{x<-#>jbtXMbY6GNJbO=W>&0D@r@^=CLJsaC>J)8C#P~w6@`Y-6%O4yd0lH zXObS*eCfp(D^K6Eqj|~FU9o)A{^c)xq2>7VU;lx!`ad81)%V``KYOma_=j!Jz1?-^ z>0j2Dym(Z6c;JbhL+MmyVa?7okefIRO zbKwj%J?r{d&XFJ`(24k$)cOjeem7`^Q_0b5FFRml#&PM zaWz{7!$X;e zSQJG)@97$1hGUqfr*c3?<3&{;7g_;2kB^VX9a9~1;z1q&6=i%pC2J+2!cjuEamaOC z&1W^_z;ZsXIcUe^1AtyKuAOsar<|#n#d67~J>bx+SO#NS2mTF{{}xsmzHcETsmBN* zFB8yZrpQ7v75RUJG_3hOp!Sc1)Gu2?$ZLQp)NS4%q+!`Zgw!9HOUTa&seg7JA-{m^ zN8r!D5K=!qJxv}Zq~Y{mLCWKVG}Ju-f1ZSY{ww@hMy48%0LWxIosysql2-|7B(D%; zz`*C1ge2!rU2?<36`wnr5W=o;+3}odk1G)F(E*-?kqxkVQ`6JaN3!3em_CxKBjlzC zSx81w()3h)Boc|tA!I-D5R94*ZyuQf_@@EF1(~8_wJI(GcO)4}MaWb=v^CSjSf&h&R)dLlnPExB0fQXNHo<(v0RxEzfI*hf79S={#)-hIaF*nGy2r+1 zV^&V(6+j~6;LWU7+NqQ$c*a89?>V8h6XdQ^cFmnRTieB#7!cm@f$w^p<|I-ji>pOD zTOd$UD+=tx@N*0k?Ij3*EW^p0Rj?Ju!wP^ z1mc2AkYZ%P@e54L-lT?MSSEzcFvz zM;=jJTR-o3LK^ImMuGn)^7=P-^S|C<#dK7=5{A~5>Rcy*3q43 zZ{D&sP$kHQC5RgBA#Q_!IF2kp+(wozYEUl`LN){t_b^zh!r=d$kj7)<$QcZ!d|&|8 zT=)kfl4F7*5}Fce0Ie(wv{E$lIIN;_AvLLGCIvP4&Rl5<`%z>PTsFQhHvEappxC2LRafk)TE7Zsadlt`z!5W%7 zuDEJ}rva3x!%-C_Zc{g}P8ijj)6>&jCxCBQz!#IL$Xq-tnW~5U2q6udfntkeO@kZP z4{zGKbEJQ;8P^$*ZwqN~i=8D!1!=8Yj;6*f$J=~Sy>c8E3cgI-$AE+H`*5wAz7!6W zrZ1g~Qhh#?= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260226/20260226092005-Binary.backup b/MikroMaster/20260226/20260226092005-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..df35f918bfe0d5f3a3bfbfc6af5354a538fbbd24 GIT binary patch literal 289184 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 QPcQuV$1@AbG&^?sZ{XYiLI3~& literal 0 HcmV?d00001 diff --git a/MikroMaster/20260226/20260226092005-Config.rsc b/MikroMaster/20260226/20260226092005-Config.rsc new file mode 100644 index 0000000..3422505 --- /dev/null +++ b/MikroMaster/20260226/20260226092005-Config.rsc @@ -0,0 +1,3959 @@ +# 2026-02-26 09:20:02 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + disabled=yes dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina \ + log-prefix=VPN-all new-routing-mark=To-VPN src-address=10.30.30.0/24 \ + src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260226/20260226220005-Binary.backup b/MikroMaster/20260226/20260226220005-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..5b228e543599f225691d4c64c7c515e28aef786c GIT binary patch literal 289184 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

76U9--Dqp!gvL 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�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 OKmPH|LNd*co&Foh3jV|Z literal 0 HcmV?d00001 diff --git a/MikroMaster/20260226/20260226220005-Config.rsc b/MikroMaster/20260226/20260226220005-Config.rsc new file mode 100644 index 0000000..3d70c5d --- /dev/null +++ b/MikroMaster/20260226/20260226220005-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-26 22:00:02 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260227/20260227150358-Binary.backup b/MikroMaster/20260227/20260227150358-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..631e915249234d81d61d05ca128d285b996fa973 GIT binary patch literal 289184 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 z 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 z ziuuTEEnsbcCG}v_GrSIdNT<$)rwvHBk))HWt#*?)6)K(S3*2iY3*FQGx@V!>S^mB@ zZ=3p|z3cjk)ENX)trHn)p60lm;_3QxGNciJtVuTseYp@OaVty&Fx6Iw8td zN}`I3*gu_bdy!6pB=YB*tyUDCUKyO{0gpV*Hvnl834*E(XqcpCUD- zoW(eo-)A>Y4aJW0mLBIur!rirSNX18qdUr#ouj*Vdm~=CJX9X`cJq35v|O)@^0~R% zu91<^@~+A*UaM9{Muta5%e#lmqr*FSHFDrEg59WlvA%k2y|WoBmd(`=>#M+VDlmBU zI*X3ed*kr#p}8urj#g`Yc(lB82j5xcBNe{0wtHu#THamvs=G%=ckUh?^~$4j)k=NT ztMA-3w{zFrj@r)M<$B$BoXg+$KVC|6|AOO`e`!PcMH}9+uE$yTqMjb-?UkQ+<=3WP z_2#MH`dDFoZCByQp8x)|ukLY9JmW>TUHkCl+dlA=-+uf1-*a&O?Oz`Hy$`(pugCjd z@!pSq_&wje-{0}M()>qWd+(cm<&A$nIq>?k-+9wteek3+kZ3Dcl)J#-@sq{n+yN^=3o7*2M2CEI`QidzT&_B)IXniC%@)n8$SEv@BGet zK6mflo=<*t|8MU5lWTj{J@kHqa-mAn7)f8XK1asHL%55Ic)qNO)~cA}B_R!{! z9$ESV|A$XM^3m$If95^^^zNVdsf*tKxukdITfbj&|Nd!{-zts1oc-M1e-AEu z^ZiG^f9U2%W)3~}cklV$t?bvXda>8~$BTEL{J`!5Z@KOhTQ45oGo8Hjz3+PM2R`

{r)4^x)I~@15^hc=}Vn`-{K6rT4MJ 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 TmVKtD7k>QXnT2GU9XtIuwG;fB literal 0 HcmV?d00001 diff --git a/MikroMaster/20260227/20260227154850-Binary.backup b/MikroMaster/20260227/20260227154850-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ce1fee8c239450e1ff6183febf36aa2898122af7 GIT binary patch literal 289184 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 T>@z*R@Z%rPEF{zH*y+Ck;dB4X literal 0 HcmV?d00001 diff --git a/MikroMaster/20260227/20260227154850-Config.rsc b/MikroMaster/20260227/20260227154850-Config.rsc new file mode 100644 index 0000000..8ddfad9 --- /dev/null +++ b/MikroMaster/20260227/20260227154850-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-27 15:48:50 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228043319-Config.rsc b/MikroMaster/20260228/20260228043319-Config.rsc new file mode 100644 index 0000000..d5f38bc --- /dev/null +++ b/MikroMaster/20260228/20260228043319-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 04:33:19 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228044004-Config.rsc b/MikroMaster/20260228/20260228044004-Config.rsc new file mode 100644 index 0000000..4d5f0a6 --- /dev/null +++ b/MikroMaster/20260228/20260228044004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 04:40:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228044733-Binary.backup b/MikroMaster/20260228/20260228044733-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..66b3f99a8964ce802164180414aa52cca80c199d GIT binary patch literal 289184 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

!l zfzKn~y?VA?#P|?U5!7x4ra5y!Ytzkf!oZcTTaRXYJU#6iblOF9$d|H&RoLO;0JE`L z*?fn#(@QIt`!=btI56u`xK&Bju1g+SF^d *#PYnsGm+kT<1{QFpfuGe>S?H(H=+ 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228050004-Binary.backup b/MikroMaster/20260228/20260228050004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..df0d82b92f9ae63e48e3fd925e6627c9acfd88db GIT binary patch literal 289184 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�i!xT9-yXQn>>p0~z|ebZTc@nQ(BiD4^jg=&m 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228050259-Binary.backup b/MikroMaster/20260228/20260228050259-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..e17991dee56f5d8ab9d9c94204f26251d58e36ba GIT binary patch literal 289184 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�i!xT9-yXQn>>p0~z|ebZTc@nQ(BiD4^jg=&m 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 z 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228051202-Binary.backup b/MikroMaster/20260228/20260228051202-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..b1c94ca994646e871a3538aa59de2fa3a5d0e842 GIT binary patch literal 289184 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≺&FocaB`j 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

  • K@wKIwY}1^T@L%-ob=M64fR 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 P7k>QXnT2GU9XtIu(U1G= literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228051202-Config.rsc b/MikroMaster/20260228/20260228051202-Config.rsc new file mode 100644 index 0000000..1dae338 --- /dev/null +++ b/MikroMaster/20260228/20260228051202-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 05:12:02 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228051337-Binary.backup b/MikroMaster/20260228/20260228051337-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..19e3a2fdaefefa33ccb1f29982cda8c142eae93e GIT binary patch literal 289184 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≺&FocaB`j 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
  • K@wKIwY}1^T@L%-ob=M64fR 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

    _JL9DCiXq^NYTE5-v3j_7QLnzoQQ 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 PFZ}q&GYiQyJ9heSDNg)L literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228051337-Config.rsc b/MikroMaster/20260228/20260228051337-Config.rsc new file mode 100644 index 0000000..d7f2e5f --- /dev/null +++ b/MikroMaster/20260228/20260228051337-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 05:13:37 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228051612-Binary.backup b/MikroMaster/20260228/20260228051612-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..0deb0a825c03d6c52abcb313344d30a10bf7b30d GIT binary patch literal 289184 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 Tvd{GN!jFGEvye=)W2gTHalHG= literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228051612-Config.rsc b/MikroMaster/20260228/20260228051612-Config.rsc new file mode 100644 index 0000000..c8c2afe --- /dev/null +++ b/MikroMaster/20260228/20260228051612-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 05:16:12 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228051903-Binary.backup b/MikroMaster/20260228/20260228051903-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a781cde761054981f0d35b5a353d2b9e9b08548c GIT binary patch literal 289184 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 Tvd{GN!jFGEvye=)W2gTHsWSX^ literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228051903-Config.rsc b/MikroMaster/20260228/20260228051903-Config.rsc new file mode 100644 index 0000000..636c4a3 --- /dev/null +++ b/MikroMaster/20260228/20260228051903-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 05:19:03 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228052004-Binary.backup b/MikroMaster/20260228/20260228052004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..4fcf178a07ac4a4c0bc983834ac43f01d038d9cc GIT binary patch literal 289184 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 R)6)w-{_)I0GR=;i{u?pN`@;YL literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228052004-Config.rsc b/MikroMaster/20260228/20260228052004-Config.rsc new file mode 100644 index 0000000..ecae343 --- /dev/null +++ b/MikroMaster/20260228/20260228052004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 05:20:05 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228055323-Binary.backup b/MikroMaster/20260228/20260228055323-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d02fbeed013b77fc0d24418b3631d29001cd3a20 GIT binary patch literal 289184 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 z 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 R)6)w-{_)I0GR=;i{u^hj{Luga literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228055323-Config.rsc b/MikroMaster/20260228/20260228055323-Config.rsc new file mode 100644 index 0000000..c6d089a --- /dev/null +++ b/MikroMaster/20260228/20260228055323-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 05:53:24 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228060004-Binary.backup b/MikroMaster/20260228/20260228060004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..1df08bcf139de84b1f39d917482d1968c505cec8 GIT binary patch literal 289184 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

    n-OOlAThjT8@>2+yPgRB9fF9MX`n~1*} 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 PFZ}q&GYiQyJ9heSFDLv$ literal 0 HcmV?d00001 diff --git a/MikroMaster/20260228/20260228060004-Config.rsc b/MikroMaster/20260228/20260228060004-Config.rsc new file mode 100644 index 0000000..4074f1f --- /dev/null +++ b/MikroMaster/20260228/20260228060004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-02-28 06:00:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260228/20260228062004-Binary.backup b/MikroMaster/20260228/20260228062004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..300de7a4a0a01deae158296c7640a5c86ac71876 GIT binary patch literal 289184 zcmeFa2Uru`voL;AfFyt*ARxXX%`UK;o`?kz5D`Sch6PhL5GlbVG#i4VSg~P6#g1ab z-o=8wcSS+5V(*Ft{?BX@#P0iDfA`-1_qh+x?#Z%ecV^DaoS8YZJ6Wq17Un7G$QU7{ zOh{0vV$Bdj6ogOmZRegmZRfg3aVmK%n)KCCaQ8qEQFlt@@QEC z4I!jX(0Cz)plPnZ3B6X^s8$;uYq-XwR@<9w2eDbGiUNWQ_7CIQKTH4< zS)3$ZsgTGBnIg)7Sra`_aBPBt*ygB;LPZFfpen>dRfxomf)Jy+y1JS~55P>0l}ThI zb*ieXt8Mi6fTIlxVpC8R1I`BE*QVGJ>9r z$rP$?I4LlkYC(4C|Rx45`Y>Y^~Hl|(5b501RkVk8uBTM#MoHA zt^>&>HINxWhifvDj~FhwwfY!KC9;^r1Q-+zp^l4E571-ju0PghU!YEu{ycD@p$)ww z_2+@}{Pk@HLMTq(W+H@A_3c6`LhdMtZH!Pp0yY8kbTou#FzraZ03~BB5gSivL1w;l zF%XiREh$0 z^nx1zEVSh0WJ^><9)IgGK%<{Nh7NG8VSM!%jV79Wj7Ae3S%bG;o^*sF$JGRY{SgAj zaA(s_@bD`GI< z_A;k0Z*QEejF+lX0BC(P^g*OX$yW9xr~m5C%lSwk#+n+1AHsU~6xjYbv?YUp=# z7l=TtOs-WW>iWRurxyb_`k^3pJVKN~Ab^Mz2Bbs?#emL3h)E$3VlYe)QoxTW*r{Nb z0K0*pT5vXp3&NPFA=CzSHcS5m5ZH8m8`RkpeH*Tys&9Ky5t@a9*p{R){(}$&2A(9G zF|b%8gc#$QlOs*_I>!njCe@(sm^9F*)|ym}mWXqb6ADRUtkwxYaYhJtt}`vV(f)`I zGq%)wo48cgtL-{>MQWp&4W9TV9o&7mO@Rw?LI}6i+Pb;k*>NE+sJf}BpV1wXU5zC2 zIAwf#4O}q4=wZ_hDhZnoCX3H7f#B+3LL>mzuUd+lSi2p{cHcBKg3)Z*Lo3!)pO)J! zw)f|BKFIGQ(E;FGUVLYunK-@8jT19l*I6(Lp^Akj-b%Nq3LP{_ zpAsiKtXdduHzudC*(tRHK*P|fX+k~qdjNe!5m5BxC;>ntx>}I{kyAe?9H!A{fKo@i z-nU|7OV0}f3I;t!&#&2&Zpqb@>J(^@dee&5i5xl66m#Hr*2+!?06T>TT^n2UngMhN8_ zAzKv0HbICqY!E`E>H-7DFy|m-PHM~Q>S~iOuVs^(xw^XA*l;aFf$PpGaAU)@dR++? z3**c?p&Xdqh=Ndads0qGNoYh$D#>YenO=1eLeeOiDqi6kMZ^S=n(9RMeiWNf00`6~)5aWF{kfVy6p2;8Nq-%$eGmL>VB4-u7 z_>=4f^ov$$H3=%MXPiVCZy2esNB9UrOmi4v!^IkPQi58gFkHVv4?P@Lpdj`fgeXY} zp@|5gNeEHK0fgDGn~V_CIvQHjVK-B+H)nwibff5?pAG*}!@s0D z26p2CqtOUCn=4`^nrKfwXw%^IRM<^{-B{RV!7decwJA^=`Q#{N0{s4+$)YwLfC$Q1 zk`G~fpr->IAD|$1ebR$~iJ=!2A$x@KsK_2gYqbetPtWA!WDin4waOR|nJUh+LGAyj zRf$?cEmcX>a`K;!q~)B65a0|HKn--t7F0jXKNJN*lzIqJ91vo9IqAvg45V^_ohvyr zR9DwQh?xQ`L$QXP4P0$t8m5k8tbkN?b@W2cz<u8d zJvHEXMQeK!z`^s+gy*fJJ|z7 zIxZnrk#J$&-qMG&I1@PGN!;X6e}r zfM!t;Vw%C6N(D_#Zx0+%3?c4A<#5VxrH^b(Qn?ylxQHFW`tI9cF+ItjhX&Xy901 zPdXq8wKf4hqoR>0;}t6S4VzD`qt9oCBEhEu_#=SmLI9t%G)eyrbR8+b z&=HYe8wsuTPlID?-2_OY023e(j0w*f!O)K@ID#;mq+jR^^Oasr!OR6w8BcklQf|Nm z1_w4c+UxG^48L&}q9IDB?1%viSpXi{Q5LHt;^Ny{fLRZmYWkdR<*z zE!4N)R99EC_3eCwP}|QGW1M!&7Q{*TqsWyry@Mw-4EwVd%`R)ej&taJ#dqTeD7G!@`5TgM4*8qE#Agyd;hQ zo*_}y5b7jC?WswW#uHi~4)Dw}Jx0L6b@lBn#y;leQtN6A#_iFeHYs2z9BS(%Jk>MX$Za2w_R)jh9Gub z1U6F!X>x$io28Exj@6qUFt3b52o2MZ;c$d>3T*<6Avv9cN6d0`B)}tv5EN;7Tk4Ob z0SM!332rh<)}Ky+C>v#NWGWaYEC12;0ke-X6@q-E#is#3D+t`0ps>J%&vSGv@Io%^ z=E9CtKSQB41R-Z@T+9`Ug$glGA{G*2f)GoDa_HMBJ7Ut4{1<-|<(QwNT>l%C2ccrw zFH!CRjxJAt{VvK@xLARS<%C#)i$%CtF2)HG<7cJMr4JW=86R}G0qor_+kZ5%n^`?(}&vfUkm=MB>R6ovZNBL z8C;kJzQKA)>;1pPnjRDo-s5)>w#LOcCT7dUTwKhSiP@M~#wIbgboXxMwD0X79qKke z#~9|iZ!qp&(LnyIab|^g4eJ!p!Q1Kg@wOuI7K&xKScr>xA~8>)Lz}TTy?5m6KZD9n!)^XCtlu>{!cwjx^XW z-yl6`v6tdkWBu=CTF2s2Tr5|J36WTiiRC;U+J$8mr!O!lf6^jR{TyvD)xJSH{X(x_ zqTRq>5-Ukbb@ygt?g^?`_raO{o9RnIh}mKuTP!8S9EBLyOs@=H;-=;#|37~VC+oyQHu{5$@(!D5Yz7b6I?Ma6!WEGo>0u;iY2;H zzHJ}Vi(6pyM-^P)&rt?{@*9+|KX3C(-nN&-%hf8S++8Rq*ce7ABm`TI6Vl)2bt_zq ziP-`%&I4OUBoIq<0*;#2^PailwqCnY{+MAN^c}mENv$#8z?uGr5KCJyf64AfvB}DW z-_~n7yZk`LO2CK&2*dn}Fwz>rG}04>Swk3z4e1FZ1;X6d6XsBD z!u0tCVaO$S_gEsHB+TJHNtciB(Gx}{6!WBF0beW^f_|4OenOaUt|bYhyWPD%YUvF4 zxtu_d>>D|;DBAiyv|>v%B0umI|u-NgXiS7 zf7o562PwmQkT^Q2SDfSW%l^1pcl@4OH>yDsVw+#1$%NJ4FG7l>C;w$s5&iB!>NNVZ z#D0#EgI@gs^cap`iLkszgqP_>xK51-L%3Ei!g3H{l}4xAg8SFfZROvHFc~+k&9J3G z>X!}+KyHndr1kbAQPuyO98z7UZ`KdUWdvAkfe>_oK9&r}0u;p7EnM3oM6pANT>ovL z%U&WEuAOwb43IuTuI0fxIjremcD5&N$_PcG?i0LM#Y&J5%h!+H&@_0&TspMp$K z5Ze|oaHy4<3#-I+5Q24jSmkHZfcvMWv_A(chE#n-?wt~5JF!zLnNTzkAx58~UDQ~} zOR?%o2HF`hx|6hMUH3CUG$0k3I>v-0b0#c`F{-M8&Q-dsO&YmOMQEc5HSXl@)IFZi zIsySnNqJ;lG9zPvbxpJ#R$5||a+xY#t5(H&%84YUjL@S^F5}5!Rf#oga((sxfn#43 z1oi^(C`GGVR$#)K0+W)ZAIp{cV+Me^5FWV#c98x7IT6knE;XiEm%KH zOo&g2Gb{$edJ}ALwA5$XKq#1o5CujmF(FDVk$=u&fORU^;8;hu1_o(bh)L$<=yK{{ zl@K;VA~MKnt zOW*)V;W5>%e2}aQsZ^~HVubHnsDuUjSXGp}L`JS!LNYpRkSYQjz%xqU23!qoU}M8I zz|ML4Yc^8hJejUdV#z`XasU7XGI<+>1yeNyH2`I>nWXkVAL6<8vG5--5$Q(#A zApwZ^GfL12S+wduG8$y&BkgzSV5}zMR9YhM%h3R3M=?iLz{{le{#X1^lkh{Y2Lu4l zpc`O;93!eZ3&>K3v^U$6dk=Nu57@gsNkPvLLLWh4=+}!Y^=()SZVXxn zA@qTKokF)Yi-mP=cy9vXjCsp9`*H?dTr95_#GZsu9u3ivPn+&x7N~2RE`+wJ#>qEc zrcO=J8Y7?JHla9s6gfjcK29146s&AI$pttclX2N{wj3w(#gy?;+Gv7QvmWt;7BYCu z5P}>;P>mF0gc$28n<-5YVyw+upqz*h0 zX>Og5adJPi-0JQ{M;b)W?7U>Fk3V1S-s8eqbvySn>2oUjFRy=TdxZ;q$@$LqyW3Ce z6Z7(V`nw7r$8J0Rq1whq6nA5H^l&&HAr6_vkGb>kMCIN7B`e&AE1ilSE?IiExl!nD zY`f32(yQG*l-y_=+E*OD6K^%|lKA1`6o;|RW8R;cs9C@F$)eLnX8z{FPpW1vUET&f zk9ha$*$xroL#Oh*@Ie}?v4`&t#aLVEX(8R8P~uwE~3M}l%=eK4wnX+jnm2& zIJBKnQn|vnNx8+r*^k1kimP^C_Q;H0qG+Azu9V_Sbm|CrQo7N%Q@y7k3=caD-Ww{4*xHOTUqr702 zAGvl>XTdh@;sZV6CX`WcpBg$coR&RnN&M8K>ojW{9$|!*-p!oJ-;pD`JjY_~=72N9 zTD866kT88f&r*KsvZ)RFF0wl7yt3|mt7XAeBkFhGw{=sOk7c7e_zmX8cr7?Ty;pt7 zN9*DAZo^%#o7tH2UCRc)zFJhF+d|ur6!*u6i%6r{`hJD;0eb4t|nh7rSEn z)9KsSzdDr>o6@X^KK#;-&f@EFcq#y1e(MzH5d>J0y=7|Iv7Sc%MnOriUN* z^Sg;32pxx-m9Ve%8AdaARy7(Govln5lGygc?Z{p1wr$@j_B`+KF!N^P*UUjPDka3d z6CDa0#xJahh%U=K6XH{+;N`WRm22)b--uuNM>OxvRgq^Oe;@k2tGCN`)-O(R@Sul| zi5)b0#DcJW8QOn%wh_l>czFc+u(k+%^Wy8x@XkqoogVO{og~lq#eVyiquYgzacwuE znR&uh+gF;a7or@mjKN147lgK{XF-I`W#ZYarPNdVySgQ5GZqZJxA5iOE`$C43ES56 z>f^O<(>A=gu;%X4;tiSSmWtO|w8`PV@OsiEL|ot|v$@s#d`Mu`*m=2^TxFNW?%vrT zc>nOhZ?a8I%Sx{n;SS|i?fk|Ojm{W%Jk#)^`!nhJtoW=5^STRUe$qLE$D3|w#OmW< zw<|w?)qzS^tNaoC{j(Pz3oN^{^<;V0>b7SJJGGozKREK4jhQ%Z*Mh9|)`zYRd}I^t zbS6!+pk#4e3TJrP@M$U1R~@t^CihqyFUw0BE-ZL_Shc@EObecUV*tN2#39ruqJ{s2 zfdiL~k1Vur7;bAiGPPA)c9Sied?PzudOB{|nK>y7?IWi5yYD$arBP~Oq)a*XRP1|Z z`H&m?&b5_w8*=E5)ZyCZH?EUfd2QY6Q(VB|EqvKxfthOhhjIG_;k1N1{X*+SY@0r3 zQuBkI>d#*i>)t-Ilfc4x-P5IvOMVf-zEAVwTW&jBa(dSqw;i*Om?DI^7-1Pkj#viW zIFCl9P^nf%*CVqn)aK5m^KyubMJv5i?_%c0%od|NjecuRp_m#WjDwqEOk-Miy0JC2 zdl+tu*}xB$wfPrH95=&QaGqvO3&q)(qn$aMhvRG^hO@aC7GY=3=3{I&AH&%ko+tuq zi8sfZ>aPE#j>j@6F13N87$I5)#R6d&6c#muLP6(dDVCPKxZ>J%fqULkn%nk8`)BQ( zGh}won}cNx<>il;$1h(NeKNQB;Dobx=<}y+@vijQB{(-e_;LTTYH6%nb0YVZXhDnF z5Bd(=csn$9hgsU%R%2d1UUBKh0w#S>%5pSl$c||a6x(~o&Mu=ppO?)qkDo{R$e>PY z+qnDW9Qy6+9bZHp(VWW}lTlXU(&tj!KHY30`<1_SUtYanH|N}JC#zG}tIzGm17lA< zxm`c`npk0cUz@RM;Pig#7n_svC(fcXmwF5ORWm<|_HCXbs@FDIY-ZDJ#?az1Z->9I z8#;EDcX{dZz4!C#zH0P5$YaPzQ-KNhJ^!%pi20Z4$B5<6^5bSxX%s|RoIzz{8B`Cf zjxnu!LkkL}nog%tjq-!OYWR&&N89O>!qqt2L+KF}4h+|u}ci>h%;={=W(w)EL{n(E|w)OZ^G=+LPn z*AKch+vnUQ*FF7nh2(QPVSZF+v}eym&-zyyQqMnazI*h3rbEN|%8sll4;Qq!*Q|xo zqavN^j7~CJ#>^d$tr*ud`fzdcy;TW?ubl6F=+U~zjYhj>$(L5vmMc?It|&;Bm^*F6 z!2!`Tat`gMR+gPQXWrob^0M*~URw*>2QBcLvXf!6I%HYHKJ?5nJLz4*k^(xsPRZ<1 zX1i>Gbx3wAOQSIsk5AKYRI41W`(zk-cb%R4wC?zzNH$~Qaca6`(wPnw)6Jhx-7|Hy z<;#}4jJBxGJ|EdTvEn41_D1?(UklHYg;DD-mToYD!pM)FX7Vbdn4!BD=*xgKDph;mQN>7$(iYY_I1|T**(?`s25$) zd>=|XQ+%yQyszx-+`hBDdR0@N%02p41{X#1iQ(w0|4F4?Z?kY!C%#Mh_a z-a75mScELWb_AO?3n5FeC!wAGSAYK1pMUk|U;X)4fBsZ|X8-ky|9ZuLz2d)K@&7Np z;t2>jx95o1QW+r=%H#w`i1E1uUqe16ZAm4;|RG@q9yRiFJi1X1mQ6jgf5J+4C)hI=%Oy#XT=UoSg~=+plj{l zmS;Bc`pTKXx_%kC&_^6t)=s}74PK9QGwC#Iv)TkAqZ(X{gL5!)gQ$i8AW^Jl?RF<2VOIs;jnJOtribh}Cf^8 z_r&sx2uJG1-gk#=zH^(R8NtXp?9l5?#oTy|ZMZ*$LT`e(VJ?Q>7=``W#0hb+G0YFY-Bg0d4&Gfxdn>O`=omTu~JI5X*0y-^dW zdy*b*cwSx^KPtb+l$%on-`;$HQaWWPPQ7*8Z%BgyEuGfpowT{*Yd-Ks=;$RcuiDtG zSP}U=&aW~w#IAkCZO37E>-DNyG5+Jz*YjmJ6y^JqTQ{PNX)^tBd&_HEW#^IYFS z-cK+mM8B337}9La?5R~NM@-*r%&>X)&&c80_Qi|{v#x#5jGA}gQ%UdAC#mtSK{+p` zo}blxVBd$-y&aytdmSuy8j^ntKTs6S^dEnDTT0&1;Lf|1ZY=@@L%Pvo#O*@IZ#aK; zb+6!QPmV>Z%<+Iu+Yhu`V0FZ)P2Eu@nH%4|5W21!gxcRro9M^Q7#Mu&Mjct?cI6y@ zrlm_&V5cop62p&8bG&W)FznQjQhv~$H-!)HcCO%fO;j$LwL3p;aY5wf@cThCR;+rt zF5*~&!Tf1%b5HgP9kGDN>hHcsJ6GDoE_Vvv-1KGIiT%>?(T9>>rI~&>*!wk25x6X5 z?&+sXKTP%#qc}_Se=QveVJRiCRu&g9U&VhKiZclXq&jK!N|tV zkaKX+Iq|XF2SwR$BiD4Z^|M?{HGWdGx#xNFRTC~>%6mB`et-F~is17Lhki2ne>2$L4cnVBN!lnF>;(zF1I$v_)$7urQ|1vZw2_C+eWC zZ8|EWls<%7>l6?#vqoLJw}H>>$dyq_8KKs~mvkJ!w6D3!KUO7`#OkbkAMY=$d_&#@ zd}NVK7X@n{?G5tp0Km)e@%E6Z zwH^sXTqI@zV*`f$1{#(@TZ?5-XX*@lOGfJ(JtlYXD_od3@JR0|hdS4`fQ*a~Ci&8? z*Bk3BYcsj!F3n$ZZgJ0*A&at2lP4cpwDgJ9$r*hpOsC_NY0HDLEn#nc4k%I2dF2yb zu8%QpkJ6bZPc|62r|d-QL4M^I6^D#ABsI0o9x~rCXV{Z1ofb2$UR*oaOk_-?b?(<_ zr`@}P-A|fb(xwegncX`xI=-(fJ8(~M(fx?HTM2uTE%$t+yve+h-_f!cdqtxCg)@tG z`xXi`16q)#iRBtT-mwHu(qeVM#d)f&kGbxnSagYZrn*5he-pERh`&i zBey%$r}=#Lo)=HvpEK=nzF>NUbr|;4)?3mcA-KGZj1DY*LxQf%Szg=(pq6;h7 zB>!>eHvKoHEuOr8ZBw0JAj2fz%yt$vX1@_eqfn}At!mOrLwG&TblIVJwz#}OgZ(qt zw>i`O3!DGD7t~r2H_|VX9m^H0>||}ldVjrRZr9LtugccYU#F%r7Q5Mh3~V{7$bH*| zLshT#HtKb3Yh3PN?Y&ve3+isVm5{gaM3=1D(O$MA>yk}k? z=JN}aZiT&?Bzxa(dC5janN)G{OuYBR7w(%LBzImguUC1?-bL+QAGK` zf3HA)HkG&>u26yzA}*IJ69{EeHlIgeJfWON2t{13lq(l<6(T;LEtRwRaw(f9PzXgF zu7u0w$OIV9$4OJ^dwP^KmA>~6(p18P94UeE_#%wU=JKVu1Q+o55}Al665%odR|2Ne zkLGJgga2ll2b<~(lR$4$rJ3kVDheX)Bp>e(O^|o6yN|cKH``m#(T~%S=j+S=p`FBJ zz&F7tU?HWgsYpmqsIJEMN)xJv8yy!v?){71{ z3)@fZDT=zjGNWa9+$qKw&nxBOYmBaT&-$>xp}hU^(A)ja@ilwm&-P^7%Ew3^Y~5AH zRL;K^AlxTZnxb^y}E{PA zM4_-S)^2hsRyD$I%*pFR3px)E>h3UWS7{2`P<>*-gnnG}n>TZV-d?!6tzlwHa`WZG z5*e#C^9tSGdB&;cTN*VR8uz+y%Mj6pOwUgNg?AUPjBqSi|6&u56L`(pXUU*$>()wF z%}#rCb^4B*QE1fktEM>vO5Se5MmYPe4&U0rQ}EvXbiKxV6=4PIrf=kX=9#Qr_t0Yn z_U^5*x7~A_b*_#>&V~9BpCSh~dNu2X?;Y=s8J}dAd>`h2u+6@cv*ML&6aS(sZDh;y zA_9B^0yo`MV3Ao}j!esabtBm1TPolS zcsMR)3uF>5IamK+W~;FL*VAv!Vx&8~2KmG3_d)IH*ZjApUrQhF5O-YY*HOUb`|^Z1 zSNBTCswIc^o;?1z(J*D5-L%uW^-3$}&R=w532Wn?H=RO_#|<@RicYHK*Kh5Q7?j^- z^8OX3b=)FCu5N2~{o=`nuiLfVKXb%CbyBnJU#{F(r+k5TK$E!{yV6iCph> zI@iuKVo_E-A%iw{h^Y8@-RgT2<;wNWCtEBEo*~|Iw6sy?iIIN$JC_gNx2Em6N1k2V zj61uNVZue|A`MgcynT^fXJhxn;f@8}VlUF;X51W4UAg7T(S*>}a~i4&_BOw4oVhz% zeybIwZ2Z1e3p3=q^EsIDr?qVgH_YVzaQ54$g-Ipi@pD`HlHCYZf(Y$wa8S;S?X5Vvis{eyGp!;j!V(8Y zbQ@W?_G%r!)PWDyjGVSE{{ZW#$;5{%oHClW9@lr&ktsgc{z-IcJ8(;B9YWmnah-c} z-RsXuX8lvyc=fom78{)!DBe|^U6Z`uF)y%(vYV}2)D|x~D@S;t{lmkSss(TIoi=B6 zh#&K4YtHoQMcc~9Oy4}Q<$kw8*9ry6coi+35ZNU~wOx=z{2q`ujGM|QsQuG?k{mto>#iuopO zv6Qum-Pf;Bc6;RNA?)Mr^5Jdgc~f4g=d|g4y;#mt-ffb5)H7-8xJw74xGvExrX87i zTe7J6v8CmA_j}#nqbXSOtmW;>uAx3MnTz4!^hbcd>Hm2D2#8jobB#5 z``DJN-KR9l>Ce9F*ek;$FYu1z`S&BAoV8uAe306|y z&8bX27TmVm3gyhe^+%fQa57mi;K)cXuTRp-&KaZDNm(&QQzZKibhY)mIcieYt_91M zH?vL{x_?^Crb2fP4Zd=Q_w>LcvTT`d)%BMqiCv}^PhR!+NpvT#WK6c7>la{=m z7`}b$?#wl_pNle9pWhz1&+H#g`M}V7Yg?zRztG~qs*(p1yY0>U^jNET(8k2)g^iUY zlYh`;BkIrvX{Qwr-?*$`xI>G8mo9sAOP7o}pPbfheOr&y1B_;!5Az#*tKS<|=E$o% z>$eYV8sEj_i22Ipw1zWSev3Ek>gABJPA0sX_qg#9XStt4p=rCAo|Er5`-IeUGJkdW7HQ4ln0fw7k8(|D{__@)O393%e0-LemTFdXK5M z&&B85{y1^q=8X_Otp^T5T`YrAsdo^DN1pOK)>{(#mHqfz#{I7xga(GND$VR0)%i=$ z;Dxi%$~0E7zh<1`zH`FV1M}8BF@9$}JYn2}*|NL)yzL|J6;3~Ydz^g>TH+;2BjXRe zb8DJw<>!q(g{8+gttg!J(S~T!t@({UcewqF0@K(d3Da&}+SPruCG9Xht3}U*6z=`( z8~t8LtxBc4=N5hHRkg3%OxpdUjm?3`0f?s zU*20v3CxyHU3z-4>sh1L*9&JI+1YYB)tLGy@!s>cBc*4aui1ZW@~FMffb&T7$ebtA`Pxm`iE?u{gnrpmwOuM0` z{U041bz*l;o0cz3TaS=EKCRx7&^xwRy`X2s+E%M=2FSKKPkE;P5ZynLIRTewI{1$7 zHg)rZ21nQn4nuGyvzKH+9g^ZOL?7cvga8g;1^kGWuR8+fPvNh~{1us6F@3{}FaNKLj4pBeukHKS_Wf)7{!Ew5byZL9-gC5%Kk&C8~)@6GHMdE zzn{7>P&$B2)V9DiwHGEHLS)3J&c961_B3Qi=oT{l+2LKnLc_enI(f5sd^X0$e7tdY z{5u&P$LUxG{VJSXGaw2VM@FdCTUtP0+FBmM?4{6u3OYUFu4dlbdW$xiYiStzn9S z#Evg*F_G69f?Q?V0da=dJP9HDD2=>aZmHJ&Q@vR!>`f2k0ZYGZ17Dqk~@C#3C zl~w%8I(KG0FWUWuqH9Vs_TII&J-bZz?=W=H;oM<&&j*FC?JzrkFMVHf?!`{GPu9KB zV#MrcJ_)DVCB>ZS5>VjQf1i2AC%^oH*lEY5p&b&ZzMJ#DfB*ICBzGD$+Lp$gb-&H~ zk!k+Qg*v||gOY(|P=@~^Xw>*IY#% z&DCEelR!?E=8Frz5-Z4y@@In-VI6cS;jJ+dCdlLEaYo~Y+o)qXzjcpTtPR}5iO$Ek zn5i*y!01kt(Vt?e6wJif2ws+_)Ou^)@cultrbYWoFiB5x^7Dja&1NcR4%L1tdf#M7 zSi$NO#Ha1K#<}AzMfi+)9Mq*psb+A%RnoX4np==$FCZ*M#Ovh1Ek)%AA=wppsvne@n0Gv|A-6DOUT z)9Y+ce7Jy;zFra6+@Vmxj5`xQ`PH`fo)nwnzCGlWE5pX*3&R$S@8=iS_h8de>F0+} zn6P+m=)Hqkj|4+oe0bJ9La4U9jI2*}(Uhzd@ba6dD|3@}mf8=QeE#UEr%|*|^ay9$ z!s-X@%C2R+e)y{QR9ADi7CDW(99=l&?)fdN#%MP@k6S#ur1HY9QSBF)%p#MmEpRAF zNWKpaO4g9-@>kQbd4DzCUrp!vSJVAppy@uZ8Onqho2L*dWPF}Nu8@g%QjSa_l*t4_ zzCbFH@Pq;>k1Y_01RN1hAi@P)K1U%F;v6|9<+FJb5ouR{Z>}co>hI0bx*Q;x0xWnw zTgu~OYz0>!kqUVjTgK+dWD1N=z6|*0}!^jrO0nz&WtCfO9a&H)2Ct zwITV4r~moi0YVaHX>3B`Or;nbwM?fY7n&5&uP?u{W87BL52k6(XP@oft$E4m=dhFe zp!DF}ou_l&JUf2cbi1TaH^1TY-4{HWBr~&nWRmdu)F_YkBXjS!^Nwr1`rHzm-u#q# zG@mDy*0Ji+HCf9S#%%IA8FkIIn)c7)^0vQ|4WxgWk^J`3hLTQ8Di;=CUc>i3URS1+ zHs2X|u=Z%tq7g<=akP5pi`aHnozJ+7_OqBXHLtSx6SA7_xSKUGBy+i}az49MG0o!n z@j_*3Ma!4tAt=FeF%uJ{bv z^)9@8&YeC(H#D^a+XqWFT{W*Ub?B6oj=P8GSOXPe$SEvx; z7#HUVWde>+!4VM>E{Bcb91cgsAvh9TD3f7qwunzCL;@LGA`=k`zJPD{>RpWc8CRS>12+Wy^qzYp3>> z`M74j>O^2CI&*WD)oFWWDC1I3qh_7vn-)CWcW%b~$G&IBk2^^TwDY;CITfer#Jz_6 zn45ZpABh}%$lBy|ti4_A(UL=^O?r4tGY(`JJ{;8Z5QZ z44YFl#V7yeq~nywTP`bm$}Ik|&XGK^&fnOQilZAvv&`O^P_K4)M?YDrTp7dmh_~@+ zkY!>r=fK{^?oUsC9FnpiVESQVm3+-(*4>n>pT#QvisoO@G=wN=)c=7X=l|QH`PtIp zi$sK+&y&jK9665=h%kYGFUR>jLL!iG*gUB~LP!)`T*T)JL~L9lVk;DEp;U_Tg_vBx zmP$zH`g`h|bgsXrw)M_6o6Y0mLR`+5E943ZpHHy)T!JIR1rn}MO1_Kyt#kdu>Fr0( zb>$zneSTxv>nrEF=1cEye&S#M;7ji{=HHjjHM{10oT*^oOu{m#NqPf^CVqZ*dEFIx zJDSN08#3SD`6`6|pSN+ywXOeI&zk+qHLe|k6WnV-ynG zK4g`=T=POac8b^Fy9LG$F{f6!-|x?K>$qJyXZXd%`NMC7CpsCe3fYn?bBM*RU2Rmq z@RDQcr%N}EO&=*(^Qe(e@bw|B&hGM9>Un#`*45(kvzKgcTroEW4VXHhx~p@5{oAO? z1rp=j>=)ZBHdah!$837p^M1buCnhv3$f4&1yyUshxD^n0J^9v$fWVEbx|^)X&e^ch zbw`&t-)C=Dtk1zVe(KVFLetJYZH8vdJE56+&bG6$*@TcY*^bQJb_?%1AN@4)j^)mg zOIZh^n!VB3*tGFW+CRo-tTQ)gt%a}IvVeu#cjOiqaz-}K{Oz}bYR3V-7bp9Qy~q`s z0a4AStLk);J;bj+h_b&hc9>W3_|9n+yGvTym92}^B)4E&i_)VyjB6H z37ex3$qBANp^$NS1eYVjaV}RzNZ0~7moMQ-q_|AV(|vgHdup;)(1*j3C~$%=5#YE) zB*COowvf-2;>`3r_{9ds?6u4H9nLN~_n5yr4ke->Ha2EMV_+xOQC z1t@b%H2H3^OOHu43k7e%kjeT-w@@(P%Qu^T9Kh+Ozt^LfO7d%qvVPrR(E3vRA19yn-S^an;m*W_mlt_?9e8z9QQ)8(P`Y$dkM zdgx>Oj+yxDN5Pj4_qw?5jkD8-wEdiw#eyW&llpGgb~&{X%32w{4%Q4Tx^P%N(P~rB zmUbSUqEpB7c0OtQp*|U{|MFE`<8R;PCCe(1(fY-Qn?y`n*yS`&_HnN3Vey(CFT3`r zO-EW3!sJverOVp=!`#ol?oM6x%C7s%hz}Ka&X}xNJ?WP0WbmHp4J>$KTX*bb{VezP zi#JW`zhx^GtKa|bqM?~(yRW_5&s(%KXhZ);8BdB|XUyJ5z1w}uB#eKQGU#!$qGR#S zOQ$z&^}LGwDjcwlAy^NrWC+&(9s2*PhyJrhC2+1nA(O~?QVe7B1RNa0_%exv%aP!0 zT*79{g@j0eVG6E7Dv~LLJhlR3O9YruBH_t-d_JFaF2BdppEat4i?R7q37b&xWda!+ zlXEeyfZ!2)o`f&r2r{b2Z_OKnh<>fv3pZSNwQ`Yz(_>2lMtS8n?`p;;S?r8Bk{UhU&^ z>Sh0voMxK~M%?T_@yPrY@$aP|+C4k%0v5k{`VO}bo3~ACg|C{_X5EO#(`Sv}nAA~Y zXU{T?D|gbgXtyM3WU$AM{>R5oc6U2@`}wG@4dw5TODq{0{K1Nl_KoE#5w)xM5yY(}Mh#tESDi zf9oA^H9+HYeH^zUK|RBD%Q!dpr7`V#JlGMU=rzzI%6@@#%h4mDUKT-{W*0qr>~_1} z&?9#ak2ti#@!+XFb#K0S`^mb~{!+Q<1FvJB-AC5?-RG`E!=AZuBVN%=tDs!xi1-bg zH~X*9j^5$J3+9U}8#>r_cs13$*iHQ@*~hoQ2eodo%5H7F=e}1)`<{_Cr!MY)*5Mx( z`)L26juSqu8n>b9{yj;*IdgW49eXenT8^+9WF6)5PiK?j%-tQwJ$Ajb_0HU;lwo;Y zd#5Y69X-Rkl)2aX_H^po8?I~jW}Y5?;IUaBfT0EZM60!9n!f88J-K{%=ctTTSJRTS zD*a#fJl&|zF6ToVa$|EdmUU^8m3@ynJnN9rl_Pz;4h+X>Zv7kOA5Rgs$X&UB+My)E z)t$CA*Y+KI*vE=~gS~feO_yFYU03K^N0s#Gti#@$MhS&ZtkC##jV7gKoJrZf#22kd zTiAW8+jigj00aHKUDI=KHmx3H*~9g5#)pFs5}Nc|^62=g4XdgxaB;?L*MVVzYdKai;Jgv4B9mDx5JJgH zH4#f_Gzn^zLK#aK;C-d<3P&g!ZA-#iU0q!biWevhRe#M<6{WGRI4l%c)xFQpfP%=R zJ_nqbP>q#|$l|I{_MR+=4CRNRo+b@yIFco0srLG>7B+xu426+vRr{s7!9Sq(D9sfL z<+{Mm8Fo@1rY1fvp{4-vdObnlxE=+u?GehSk~NUYdd^S`85*h9B%!EiC(D7XfyqKaY)dG2 z?C8h>(lyYvyOFhwVV2XCFaBIGn)OxPTtLrBh+!BXa0FaF zPXGm;ovFcHNQP+d9S5bNgS!BZ#tDhiSfvb#g91A4GF4n$V!TqTBuFlSEmn^i9Ai-s zy8#Ke6$)ZQnOv5mBMc+(3pw1tWx%d1R0U)F#sA3~&oy;Yf#l?Dt{(xT&)|?G2F8a{ z$543~Yyv}7Vz3Mh?M`G{SHRi?Rgq7n!)?iO+ECV*0fktpZa=z)3fGW@V@b%9wFxps zjdhZu#~h9+I(+je$Oaj{c2WBqQYK`%VPk}5ks_N#A%&Mh*2NyGD*_GNM%HD9`op9+ z0RKM#03QGk+I;W6P^wj`R?4G@1eID_Qwn*h9yB0KzP=5FF|5hML_C5CUl<3EL3qzRux<5XG4+FI@!%z`;agGDs;l z)sHCCz`2OYf?~-~?pt3m*$9epJHj~^IOnSS2V$~-3?o2(>E!6={|^F50U)VA1=0wB zq;>HP{-1=C3UJbX3a2p%XK;6)|4BG$h6&}Tpqh~54o(B0MT*a$M5Qc7Luf(FfzvnX zd;_wGH_Q>Rfl%GoO8``tHwY~_9p3tDYD>U)Be)L~F0RgkBKOrQj;DTr>VvK+) z$RI%=GGyKFK9^EXl4=jCn6n%myA6a6N-APHvUIw+$W*VR<@zfK{ci;bAQ^m$hP#>R z{yoE7cRV}}U?7Fm7*#WACa9WG2UVfz6y%Ji!EQ3;3zMTIplgE=Zv1BVyv(rI_VC*d zc2ENw$*5nb$6?8Yh3S=QLl@ zD3gkuP4w4%Ce<(Kd>;j|fn}+rePLi?ur;8alaP=AR0G9s{2eL*69e^tiGgANk0?bF ziKNeGs?;znP~cDC39~W?>-X_wFz9p;MzBc$7nlUU!~dkjd=>!^NzyE!e#P5%s2Vr+ znpr1)Ip3QS#Qq0W=TVU;{8RVnTq4=(16w6X;EI89VD-O1)+a^TwImTaQ{S_CJ*pbLK0M%pAH8t}vrG_z$f5?tHY5i?x{EjfQLCu3un1Owx zN=k_L)DY?xb za}Lb9^RPRD5Mw1BA*k(c22XO=JqbSrTB<5zY09KgFmK2c<%Fk(&_dby8rv6w2e84h zxejDximFJ7xUKwf3hZhVbz*$HGCm57YdYKoa7c_-%3?j^RPscf&jb?@%m=W+u@MSl zQ%P3PhH?Gwb-)9$Y;D3nV}T)f$5r<)tSoI0%L|m`q+Mhz)EAx}N3eSWWsT zVAL}Vt`w;zsk(ndchcn}ZMHA^G7#A}75b(^Uzq$DEC!;IeHo++^tmrf4>P-wz^l|m>KLJ0*54fom7LJuf6^xp!d9K9&LXv+~&3WXN1 z|DW&Mx2yNotJO-e69~~KS&esBGw+yrGjHC!dEi*p%UsPE5EV>VC%`LFf{GNQB9Ghx zqfw~9fEJ^`rWiiG7=>~%&NW+Oi0(e(?LJ|`$^tgd0Lr6T6scJhoARg_$C+x!{Eu;5 zIG(DE22$s6v;Avmd1CEGS8^C%n>hSs4^f1}CwqvtaX9E9>gF(p*Rwbr_7I)U;h2YL zF^5m}5FN{5QM8_$MD#Upb8U!?B|&y=W!L?w=X#xwBv|VG{gHK8QcZ4SXo47l<&nC@&EyFB2)R5Mh|Xa6-Q&!e~Pnz@8_f*N8CI zz;>oB3MsD>(VvK5RkI2AAw=|7BDz{3+Nuy;qY!;dA-Yy!1056}eOnOLJ*W^pq!9f`A^NdG^aF+HSH(mRD@2bdL_brA9#x2*P)K=9 zA$p;h=-0&r{Y+Src}gLAS|NJJOSHpF^sbj^GZDS#C0brUzM({(S}@WKT%Yy>n5m&1sBLnjj*PNZ%+0&g9OGfY-0bQFyKRhRauQIUScX^r5BqA6`;v6Yl&I(3`lt zhs#@Dj6Fo>0K>U>ft|#10h$7WxDnQ%7mk=BER^Yv7_Rq~(eN@6oK|jRQ`w>r z39<>_Y+kY{$faT4KnSDPRv4K|*z4snqkh!o zQPPhs5JjdW`%@luRjG?#BnSIcuuYj=3LWTD|K(zvLjNhSOQH8*oBo{ZKiHpkwkd2q z*sWIERM3CBVvj0@J<9c8ADh%p0p={7Q0gLx7v13EYa5Ny=q_*a$Y>5`FU5r^M zG@obfV!I8i?C14`6BF6%o(k=soi`LwyJ2GW|$``!aPxh8tkV@q7S|XdvS#4 zVSvOj$N3>F&HA@+aW_-MyfC96GCMS*-W!vi7cxOKhCyRqC>V>7se>0SKW6?yKa9!M z%l*ri&!4-@-@N4LW0tR8ax}ZUYT+@*ES#XXZ!J=Sydz)*61W^mJ z5QZQNsR%M}fhn50mu~`ME}Y@TA)cmJfdQ&$?{E5HB}vnUq~=v@2-7nL+WLF3kWva5c04 zPTtVHOaim5Oi0S?^DBXnGkXcd3fAXR0@W3;QCAFfO1bVTzxmMJBNPLI?y56&2CEO=_?pGl)X+L4*!PI)p*Vd1- zJh)cur45>JH%MDPD-L#APF)EZTiHJ{W*Cu7&oNhvAP$(`d86^pOzKROK~Xf1HH}E! ze3Vt#=ii8ggAt4EyXesDqsHtO^I%+B7xV1I$Z%v@7V=DSGS&|I%V`1?Wh+jqXE(@F z#ufE{cy-h8pZpv1E?p;OU2A97Rt{b&I(&Y@IjoF@moY^-OulX;@|% zGRQLfHEnOKvS6S?R1gLrL?0lM2N4K@&24&k5e;NS9KeGMk1keP;I-{PHLlu6^r#2r zG3ZD^Jja6L*WzLc-f@oBVS@&X$k~OFqlDQyY=m~VuE>TCj3=WOBw}%YQ!J`&jKiD_ z1lMVaB*FlOSZ+eCm&6kqk3GG^V=VKh?Onsp-A$Zpu3u!}TqP6dy5(4KtB-ojI5un> zvg2Gx!fxW;0(+HN*w5Vif8gVja7i!tx!~hWENn(~W?nQXO0zI#V}-GGRf#Tes18}U z??iDqk1?|_n`2>SqB(i{o*!lN=G9zBS@5i}j%LTJyNOQ=?fJC0pZRnTaHq&v)__LF ziD2Kda5R|;v?l_cRl!&%*jQa++_7Qh^uxP6q65JgP<6+_zF~F1jDjM2b}i^F0TF^*J6^ReLTi`J!>@ zpp-uBy5iOQ_l>A~Vni*m=hZ=b9j_iA>ssB_s#(lbW&-d>FaZW_jCG~DS~XWJd-pz; z-4iT3$ev|Ozd$U@jDW%Iu~>UV3&g`oSL}M*K6c#`>{@Eiu4P{|c2(Qk;~gnioOSIPgRjZcO4X|%W-6M=T*q%{`e9;(H-I#Lgu)1g8kh&*^)FJkq zI`oUisY7&Ib$vLb#ax*H`&?IhgkOi+^XsrL8ov%|Po@H?aL^U6KCo|W-4kQ$FneAd z{zc=}QTo{0mDCc!STv=*`x*DQ=iLc=6Yokhr);*t&}3&SUey^0N2-K58b;?nPb?$&J`chk8GR?%bFhDJ z;$RD>fg6k3W9!9Xm;dd0yv1Cs?<{QZ_8`C}*n_(o{q~$Xsh>G@5A15pX@nh;nAup> zmQ2R01QrHMTOU}s{*f=>Tr5|PHPW#3bJl}N_MBTWV4Ryyu(I3sja#@43|SV4hpR%Z zmEpML`jT(E9&w-9H{zPJvrIe328e$vZ233e0|wkB?$`q?oYOEo6wIB{A{yIg9!s>d z85}cotxqhX@oRG+?rT7N&YWUqvQ=xk8J@huoT`0B2I7Nk8CgAeZyJbm;^HydhEyVu ztZLU%@j$zljB8qYodV39=>-cDEjK}2=@3|p3Z?gFAR zew>&>JuL4XJIr?N+!nN8aY$zyI2{jXkgCXnSA)~~%5e&1Ig;6x`@+$bmWXO8 z6aa+{bVX9gUw&I^NEcW}6Xh<0!o3HZwSN%Tm-_ZGj8 zdfmlgB;dQ7!$`pQIERsd4@ZgMgYLl@$oQZk?&L5M@IA$0u$}><_y!ENFlZr>ol#~a z;CqMv776(7;qXW#2jnmk@IA?4Fer|_#79hu_vaBrmr6-=}k26A+PiTUlC`3Qy$@O3r;fPHn2}FXu$9a-HBnvc5cO(J)1L=wP*eRO3 zbbuyCGEe%L%w0VpGo5DdIEbJn*Pg{>PvVsnE?u~+$Hj7PrgT~+OU8F5k*`Q0Ity=~ zO{5-`DXkehBhxt(e4*tm6eE`>%hkv1^;%-tD5X!G&AlvVF!V`!hS9Q;kCwCjfnZRJ zr~Fzn6=;owlO0-UT0+A~-Jxk+(NqFy|3Xklh2dztE5!`B)1+k z1Cem(j(#gD#wQdPMZJO-l^w0ljzpbp7PTOIQAe9a<(;r(e)Ed;4Lka+ta^^*YtAC- zIg6ckllAZ^V&6zDy%Ur}p}aV4z6X8jAzsuyLidbPFc3!3JySl>`NKN8lWDSten zwS_nMLzt)sQsG#%3L@VF2cPhHt6$lnfZkV#{l8)uvH!U=l(m7(W+{@{qBwiojIg%N zlA{;i)o)d`@~~OZVia_S*@?dF1s!WGXgHqKg8sQpcMp7NeJE|MSz0xFX~)@@cHycO zkM~<~aRRr&31-8prY=;>@|I*TZy!Yzh(!FUjzG%a8At^?v?Ootcq|eQZhW@i>hP=L zbR8ZV#5E3-O$jT#aUvO%&Ys_2pwz5HnVU-3TLDk? zTVatt8x4=t)vyF028?~m%yJHPQ_jgUnu&`I9z)N7J}Xzuw;7?HvBN zx3~9J4u8_y+j|R#Kke=9HGGlqIT|>lMMPV<^LL9vYT@My`Q9uf(ujOl&nEgnA(j54 zkXrj8ppO*t!QaNb!K2^}{x5F-50_`a%pWVHmVBZRYtm2ocaK8q=3ZQm_mEm!sgOFS z3OJ|Z?P`V8ku?hW{^4ckKbyYe8}lrfXP^o;R7-U*4>wpE-tBx#=tT(&2B7JNc83#M zL`x=(65gC=8y291-T^4#h~&m-up<$R#=6Wx-jHV@3kRwhhjheJ$#~4{=k4wbs0bqB zgJ`0Rg#*x#!{fnIE4$*6SRiC{_O0%V=@E;GQDdNrITFPT#k!+nL2q$iP;todVMs$k ziwB@RN5rC$jg=jNM5sHE&??#Z3>yIJVmS_tJ`A@gXVCzZbN|k+NGhzCud<&8B)0B~ z0$YajlKvRZ%lKefnd}TiB3N}Z7X%Z5Zu||6gw-;9@NGSk=Q90W&S} z;ruO}y(KL1F*oyf6jE+dh;CMhzN?rnXX`!_GkEDvh3GEJq3f8f->2xOxgfX+anIQA z|3e{4ALkTfi4RMESUxn)&%zQP&fF50_+YYNNf1kbSeC>RAeQ}b))toh;E?{8m&_9# zYl)qN2lqIRk?gJGf8*F_{GH#i(fxUXQ45wUmg6D?^sUC7HMm$73+;~I$n{W7wnVto zOFqaC)~@t*LUUd~=i%N3MCv943b;7==)k^9gsOg)SGJul8IP$s-GoM5l*60enUjRCE8PxsASsll|>Sj-6)BQaklCJ zNn(aGn(_(T+S?`3B0LbP^qEa?r>Fm7i~6}P*2D2z&=Om__~PBC7)5cUed3r^F)GFh zxX^z6trasIK$XvVX?v$E8e<_lCNOWsXdD{^0XATZY@4F^4M`N!x>47cdZ_VUtRbzo zs$)2sV5{y{4LOh^nc#jv=37xzbA>Lk$7mAL{UK$ zDpJw?iilpovCaCi$inkmP?Nl~#y-2t8`?GQyG>xsy*1J8PWZ5$!sP?C6 z<+~wzZ_!`8^{DO%#V1H7);Ub+RP{|xbr{QcWv5eyGehz@Lp(QeWJ?ig9k`1&YW6h^7u%jD zI%&bTz0}vxga}qO2NLW2ki%ds8r6c>ERpo5Vt#EyFwzy$^ss8vHnj+GKFW0vC|1I> zU9@_WyKRU4u_pPMaJ^gm7z`LO3wxr~wt15;hy@?H#Uf`tDJ^ zY(WZk={rPQNa;{JMTo4)sRN z2-`5v$Pd!HvZgW^@51JBmR~^cUF_)(w|#>?bsr$s28y7q9Wr634D_> zsfeheh?F5kqzo-0<)$K{n~R9%7LhW)i0Fq!q|$@9Jc+M@U(Kr8{kg@9O&fIk$HN(+j}H%%d0SVXGwT|C>4%N@AfiOXHM z+>HxM55Sv4N)MpN=j0RFqi2X%pfDb$AMnTIr8jfk2#EJi6!KOSwk zOHoR>%&$p^jd0~|ew~ZS6^fpa0Pd?yQA)7x(bkqIr9KusT)G$s^RNs|7ZxIvGP#`* z!DNk6dQ?w9pct-axTUR;N{CKEl$98<1UD9Qtn{M`YY#5MvOEU;7N3;1;otL;nhs7< z(!ohXsaH>B;vzx`0;9_F>a?dBxdLb^E?Et5*ays<&;ysgia*P7F}=)WvjJfR42_BA z1}(mcJ{*;{jEZhC1Q+USLg~<^0dkA&HDa5q$Uvg}8x&9F|Z=8=6W zR~z1veIzeK-bPlHbKz1>%POR6PSW614&3Muz1x-!co5ym==7-|b8W+<>H6g{N&Nre>AswHuhEg@weh~(2tk?FJ3oOGL zZ9bX2a}!180<%bCKls50vm8LO4$VElcS<_I*BJgXi{@}sG}{8n6wA!Bi^6z=gD~1L zB?J_V2_Xe@4s@(Nm^Du;HW$Hnj9;?)qw}$1#Q`7}m1y|4`b!8^d!JT5Ny>8*LY|GQ zKdsnwBCcH(LP0r7Ldb?dtA4C9h0q~ymfuXAwTl9J_GfsS2@Ntp0-93@{+<+2Hdyzg z!I~jbBA)}0_qc$nO24Sc5^08+HeuP==x%b!%u~B5B@ABsL@^M1J>eZ9Df*@jb{AM^ zHDsYP4P(}gVF!bk2OUbr-DQftR%-+wLPr|=)-oBzh5?wTaqL=0=4l)&hH-2d#uh_W z$z-U)+tc5A(msM>x5W4MzoqJf7;bh{lHTkyNE_%jxr>r$RkN0~NXQAs5@)TQ z+rpA*Em*a>W$tP%bjoMkg5?Qe#SlW;l@P)Ve%NeNS2NYUF-0AyouY>H4un)@IA?w0 zZt&*p#t@3MH%G}7NSMj#%9LYTb3wa}w3@5PFlsSM-Fa^ivy{noio~6soU^}v7G{`Y z!sZ+!opPCB<}9BBy_>tgHD-oriIKZOHv4l@sd|{rYPV$@t0H-6yZQ3v-{ml1h1|S{P~X2^#fzlh=a1MqbxA=vP5g zDnA-Tc6m<*+!wnGni2~OeYB-v$sz|zjten;tXU^*DK5sq_bU2gjfD@VyeIvwDM#5$ z-sI1loEX=aAgYM9Vp?l z2HfW}P3$9B{UK1?iK9HI5Iv+&f9?)tfg3YWlWhotFk#aXUMPhGc(4zT{m+p8Yj?YB`a^RfRc)V5AQm@`8_l`L%vi&l(2thve)eKn zz8l1HH?BYW%vgYo;%E~v$22E1U-OJ{Evr}fgY0~~B=VX>V!=SfA4q5ce^gJw zke2odrS}w|EV?8$*yHo*xz0j_uCD!2q(|x ztBU$pCI{TflNK5~FHOtp{DK1Pv|~DbGz74KzB-cF|4k!_{SOgNAq^2-&#s%<^=fv# zg@@r{h{_|9_~a)P}W?~XjvyHTa4Lwa&nsb;W1QLHN!@7jf>kS9!C zxlb%_P)q}Nm(OCbhM!~d`FR)1iS}YSVK->k&zV^2G2&3E)2)$qsTj9iBe7V#H4t3q zpMtEI^XINeHqULDnpY6sd8QDjeYi|#e*X2On{~{5XPitRMICAEbQFUFb~VdwfA0nH z+Y906Dy!|8B<$0&i>k{hmX3MDB`*-0T;wH5vOV1A3`Q-P3baPT$qp?vEulpMDJ?Y3 z+|-3-%(VP@=$@O#LHEf!uZ$&1RbLy<+uNFX+oO>} z8ksuMTF$UCcS+DPov1KSJ{jd&h3vAkyAiaUeKDCfKJKcmiEJS@X{7sI!yRNVaJx6* zWxr+S*ad;plX4h(jR_pHJeh_|8=LOd4`F8-5`}4ExtXJuoskfYMUi7x%xa6Ex;}?3 zB+X;Lkqr*)fOB<9_+cB!E?Z zl1cxvC978ZXZxp0SvoK4fBB~jC#npT{8I+`ceA?bR{qTsRR&nmGN184q_&%4EBCuA zU3|al+J1^jmqedQ{jSY3MftC^mBr(iuUWlj-a=b}G)_MHKhyW4&oi+);$e~5IJ-yJ z)cqWxD}Swu9Ohz=vjvs z=JMR{i;0w_M07L}RU^@64UswlYuv+#JPkbS`%Gl|Zp7wWmjC?(B42eEAr^vtci>4F zM!G_D3UaTk!yg4i5#-A4B=Y^kOB5yY{l1VWM&$eJK}2yP^(ZjKge2eA<9lCWDec*J z0dTy0Hd2bSpBM4(V*c&p-zxt`ih7V4MC4ns2&ZW2f0q&YPJWYUFz~HVkg!ud4(C)M zMYoE~e(Hp0aM=%Yiv5XvW5*I5fVcgG43z3|&*8=Aafis`M>9Q3q|W&{?s!-#W>(vB z{u|_Pf|pRGV~EhJ?6XpU7YgtK0iI7Z^xwx1pQ{kjJffku4gVKF%)CrI%LI6d05=Kn z6r!PLJ-L!)_n%BO^jBMvzMSYl;hhQr##3->NLwEXCsUQ3T4$@4K-zNf?7{4}s1M;+ z?6ZX3Z>~jLM+x@7lR76_&SDyoH!M#$tGj!)2Ob>EVH|i+#bKmlHDJi0@eaE05dIG8(ypUtDc{Ta{RKQp zKR#%_PX5kDqo zd}FY}HwG+xW6;7kQsCnoe1vZVAL1KH!tjlZxA;cZTYMkDzmf7DesXI}?0#i$cZJT+0^WJ}Nd4;4@mqlJXcI(T-wL-Yq8O zV;?DnDv`%W^gW-xkF6M^jt@Qm&@^^Z{TtTE?45xhzGNM`VkF> z;YV|PqF}G5{)NkXxcnQJ_i_0Em;d1MAub=`@?Ts&^^x!H z8)DRhKX8hQ;z7H6aVb#s-Yilfnhi7zkB8&Q2wX<0q}GlBG)^VeJD&ZdfNF}GE-mwvXO!Eio`FE}Ut!eQ@tP}7kmCETIAC=QJJ}NJ* zYiwLpKewTJZcX)~`*8QgVk)OceP$}_e|k-N7@-SltLhg2UKq|i*@m-PyWy;++HN?j zsm5^DwQo4faX1^I(gg||{06IZftL;U81nIdcMWwV80r*hs2lhJZV(2z)E*n)6juYB zZ{Gli0Z#p&Il3t>Mz^8;JG#|WXBpjwVs!J=FP@{MO*JpZHiemLlZs%f`9A6G?KQ2n zGInNFjla^rCaR@|l2Y!i_SduFuBLHzTWI#oy4eld?E1#pHFa#b>vPvf%G4h<*OnIG z93{hmfhhyYh5ZO)_I)oY_yflEzrCb$SEsQHd4 zBHdaTjmKjPNG%*wK&mpXKv(>j&C!0i4b|9FK`gVhX9C{-z)Px!shzQ(rlQAJpN@%4*H?1^- zx6%yTR%)mX9XI1P@w2V%s0S!}ryqc!G+a1p>A@Kqw_(1p7L0GwJl z6%Xg+4e=4FBSS>0ryZxL55+uT1n#YaiwV9n<}*V~DcodA03)criu_So5NDqW7 z7doT_WF|S0Ss#yr%xjs*{6RnGMfnTqVFEow^jjjF_oC9@Q1dqc{R5Y`aCw%{T_E-gRAe4`2D9uQ%5(~9^BhgK4g77T9r%%5)mz#tV(qK z6D{~>qVkcms_W`&>Sol>sGn6`*D#~Lx~_KC%S7eAxRzWONYvNAf<)`ADPBh!A`2ok zk8c%6tOyOXz@dRu)(;C~OIDzT?#t3bEU_IrrB4fyLkpp$SPQ*Mw(2NcPVO~0}KO6=%jf)n{tZP_U-&ixtbQtJ5+UgT!leuv(3xn7h*#35h?Ul9d9j6rxHD*FfEI5274j*t7 z^}#U+IO^LwPOA(AfyStq6;Yvys2GTfoe)JuL|7x&+al2w(W-fSoWR=v?eS#}qdiXM zuy|o)w1VId>`@Dc;7^3J7Y$oMK`$hoB7PduQc*2cnbcCL zaI`&%pW*{9Hogx8hmjtcqVR7c2F1(&2CD9GLc^Rs84b6!X$b=r5@_S2C(>pC1gupM zS^-umKhD)-jbwIlW-5^JvnHzg5~g`kD$94mbP28^~gV5|ig zFgkc8f4@w@{pMN^OBbV%u?~o61cVWSxlke&m7{p!o3OqPGPbXyHTu4e6577*wS650 zx4!NHD;BWVS4w5~uogsnlu-{0gM@Pet2ii5p18&#{B?Z^HWjFL=cO;n9Fihe{XcIk+OVM(l6Fa~u5qQYG; zLcpMo4+baWyISW>^f@|#$s~M@-Xi$3;BZ8N+3jNVGg!Veo``MO*hhK{*2j0L-eD|a z3oRDWLPKE$L)1*?^VYPqi~sU<2SS_mOwc%-u?9t}-)hf~3h z>dHVQf;W<=WouGPtOt3ZM(_|m_#Ve==^;{3yAUK8*$g0xiEw;+A{<|*ZNyLA@BkVi zp(SIH^;%+jG8IULgDVuB>WQ2xdO5^lw5L&xwNzC%bFKQYQeC;AWmU5sZfo!5+$CnqtH;h=uzXcz%bNMj1aXC| z7060VWD~5&mMv^y$eLK*)wg8RsB| z^LQ;1iFGryOWmL?2ima)TJ=D)(nWzzq-JH9j(3A;0x*p;F-9=DYT-muGOvDH`nuKTe1L4{>yBbRxP*t%m-J{Mj3D1@ZmqC-C+7$@Rs)}kX zTiMY0_)E~`wp1itcx5~u2bI|-6<@AYYT*IMs@E9j&M~QYWh%pB8^WRRX$WVY!>4PnR4$lf-mlM{b#;U=PwGx6JXd$$kk) z;wYk{Q0oszO%1SJQV8eJw|;Pm!dIH~{-Mp1pZ z4AOT{NS^{cz{E*CjYk`t0NYq!v%rJ{6^tihZQ+P!Ow^9UG>T7&zRcn8dx(xxnrlZf zh8V%FlUSnK^NIaI7ZTA$M07C`eT|4NVe@oSVC`e3x(-{1h$uxwU6{x683H0;&^y@9 zSeu@5vLwjN&|=L7@xne4c4sXA9>>42AxpuAEQG5}z#kL&AAbH_fz4(I!tHVpzjH7; zV=@ooK$Zxc)2(7|!#A(7WZ&o!-H(P=D-LOGfv!lZ4vjhk7uNWP3cWE+fQR7?#-gJE zu_K|T*!0ntcSpOb@IUr#ROTWR+Eqp7Z`O{P8?}ELb2x9zN-Y{pY>cPEvFI+eYXe%? zu5mFsfXB6XEZ6}V#s@czZD&p08m;D)$M6=hl@eG_|<7 zc2aMTTGHpY1x~*$lzxjv5VNt<#1-oCp&B4l%E^E}JpNOM2r)P)i#-l_6MU$?3mk=P z){706C`+kA>V)M`%mvu1*Q2Hj2EF7%I}TEq%etqWHBqTvBJ%h4sABatVlr(-3x+gs z0v);nE$(4BQCc1WcKL>*UO;^%?5t_IXhO>e+u9*WU}VE>51ul_5qq2A!biPYJ%~QlJA9fzW!3{Sf4QhVLLX*A8K}k>N8RM1&*g6>NlrOBwnL zj+f&+y1B!=sQQ4*T&afo_xXyMeh@7WW^`b5iKgPl_+)S`zR{$mOw*PyMO#3m6tO{p zZP-*)B4r3SxtLLd{mUtA3WhZSYYIyuDmGm*1B&O|2B~DY^Cat9h~cHh_kQ{~1TMhd zLU?A|!imoAKtjWoO+iN6SQ@42Nvv7`vl}tTd)Ukyj;9(bqXA}Mx%nL$9lyg0OgnNX zf**ivI=5AT1lvLJISMNvN^|W_FHBe?oXrohF7c5E{%XXx>748N;-atmx|cnHyRbG%h;jnB^PSEM9r++PTXk3uiU8b}pX3;Q08ml`9YbFdZ^? zd{i5TcsedX_>&5-fe$zv>W;6iU%2Lkl`B(?3zukfmma^M@zk}cLsMGgsp}Un)Z)=( zcW7RF=V_7S5C2q;#$&=})hDG;cad0oIEsdbgBy*F4?O$^tan0lEiA9opS?PaRs=lq z!W+Zrv2M0_V3}^b%Ms!GUB1@iVLoRh?%9tiLu|ukLWJH0Cb+k;vlzRI2{Q@>7Y{C8 zTncb0#H9!q3^nA#Ma88A7mPe8J!5JnwJ_Kry=*~l7$z(4dr>E~U_8Xk$D*_Kfl*JT zbT)o%Ni}gk?!hEfyS3IzR$&!($!Hs+593ZW6|cn7g_d9|eQ3^kyhYIF28=~y1BN|e zz~J$t`1?%??z5#!rp%eK2W4IWJGKaeObP2kN zi=of~Lyap8MGhEhU12D8z%av#;iz;w!2Z$)+hH~sj2P`yxKrcqe0Vy*T%nF2CVuFf z=`m)U8q9BK9av{9Zvv0-=L^TI(OH6nQcSz_<-Dd?GSw33)E4oQp<{d)RJ-xci0Td1 zGbXQHe$3H}k6FHE#pLP@)zz%8U{wtd#bD%BCbd8!*inhB3)nW_w|p4MF>Mz$BZPG_ z=MbnEBS8Z=4XZx*fYXfSIB=Q)gVPKcb*L(>{~pqC9841ExP2ZMs~TZrrwejmDW zssVd+O|7p=qomCCG%H@*w4$cIx;{EtH?A*G%y;x$5NMndgo3A*h1;~6gZsRuTXc9$ z)%|)4wDskE-qLM1yj9Q~UVW^-;wVznC**j6J5~F>Qe+mI`|bO_Qk;H8_w-hoB|+md zhA>|lCii(#OZBatYQD`^Tb3HC&0^Q;ZbHJO7<%0{CPGI8lkBQ0y@_pL#x`BG6Q zJ2!4hA3SB|E8=p<)IRSGHs32feA0Y&pp}2gf=QS-bi`80cq}!&I}nLzq006^BBU|V z16yCuSw~dx_pa5CvY(oJFC^>gQ%Q-hRY+kJdBG~qcXdZ zD?}uMPP&dl5Hx8hoX~=p@IX!4%bE+bWA9gs@X8Tb6o%`4UQrpLw{fa8XtU* zXT98m{jj8#fa8q$Af|J$*LX@zHiRu0K{VZ)jt{FA;2HtOgxH87n<2n;UOg2NKJ~)= z1_7Qaz>NYtOMqt!@L}HcfIdgKf4Bf2A;3op@KFLhSAgdU@O%MYAixU+c#!}v7T_iU zULwFt1^8$IUM9fJ0^B0N%LRCa0Iw9_V+44W0IwF{H3EFB0IwC`;{^D40X{*1PZZ!U z3GkN%`2Pg>Bmr&{;C2D-5a6%?pCZ8P1UMqVodO&c;Fti%1^83}P6%*PfKvk8CBW+i zxLbfX2=GP$K23nXBEY8$@EHR9RRP{4z?%j5OaVSifX^1-a|HNY0X|QF&llhe1o%P$ zzDR&C7T~W5@FfELbpgKAOEi~BKG9{uIIu;4FBjl%2=EmGe5C+?Q-H4$;Hw3As{nsX zfUgzcZ329q0DoJ6uNUAO1o%b){*D0OB)~Td@OK4xy8z!Jz_$wUZ329|0N)|NcM9-b z0(`ds-y^{H3h;dbe7^vHPk_HKzz+!U4+Qv!0{ox=KP13E65t;T@J|Hzrvm)206!wY zKNH|b1^6)meq4Z`5a1^T_$dK~GY4t%@OegnpB3Pr3-JFF;9m&vF9rBH0e)V9Ul8D5 z3Gj;o{A&SzNq}D#;8z6rRRR8u0RL8ie<#4d7vMh#@M{A6M*)6afd3@Ge-_}s2=HG8 z_-_LIh5-LvfRWqJX#al-@S6hsmH@vkz}Vhs{C0-`zbn8y1^8bA{GI^+TY%pe;12}& zKLY%r0DmNmb^jIa|IeEa+56Z_$Qj5!>O1LB!C~*D!wE+V_xFD%9a=d1owQAL_&bDr zfb8RW%!4$K>@)r`5Ap}H&%DPxrpsZe@XnQwd60*YeJ*|7W47BBucz@``=>OXU;WjC zE%EI0;$J=V4G#bMuO7OT!!P~SL+5e$j=y=>LLxqQ{>@{C6W;YV4_(9Gx%+SF-;RF6 zLtFX%F>iS2eh!a)!^5)g;WO?H4_l9(=C&$YZY8m#SX2;EGR~>ZJ!6L^N3S(smAq26@dk)CPIs zykei526@fU&gjteJO3H!rJwM3J{;+#J30K(NUzx@2aZm^fADCp+5VG9d+9p<{*=+_ zGE5!qrJMQvLq?~|TshiH*Yf*SqrEr=m3@9J;J;@~n%2EzylkNvpKHf@=?49E+BVjU z15?>&*0}Whv&VVq3V#2vabA-LPVlGSdHdir9GdK_|(XZoE7qh4CY={^+ok`dDWqo|hx{Qgg(UOI`xA4Su@oe)dIhYIlJ0{nw``kmJV z_~BF2_g@#_>k{ev4-0U4GJSug0G}_wKM~;XrPA-eD8R>drSG33z}E@zBLe*Y1bE!~ z^lujk@J0dtM1VJRr{6zdV;X)?fLDDbegE;(({TM6X?XFbG#nA&H#ev6m!6r17oL@d zPZr>)0ADY_gU?RCKVE=O6yPlate&5K|A-6I@P7n&`6cQ5qb^Oue;43yT$aA?yF3m5 zT!23m;G4ghe&@QY((oq&{D*7P_mA72hW~VH8h-cLGXhwAq~XU`rQz770u#@Rn+nXa_vvYc<{10Tv_ezg9WuSp#ChTTH2mx7#U|ax z>NI@wB-PYMl^3e!m{xV6O5fq*#*7P9b37dNv}%sk<)ceXz3|2hCFVPKepF`Of8e7s z^ZrX8m6M9{BTPMe?$smAaqokxN0_$O zPq(Jue^P*-65y8~9%1TM|94=^HP^!VE^d-I@s$m~M5rACqOj%;UmNmX*H4}Umk4{# zd~~aiS+i>O!UfEAX+gwRv>#l&s6|8sN1ccW&s`xxCKwSBynG@eJa>!eHW3kAgcd}% zxkU8rqaq^s7iC1xKH3M-(U!&*5x^;FAV5Ig(35z1ip8+@AvO7xr0SHQga#>poRh2T3yle~&lFF3FzL|)g3yb>aKzhy*TwmiJs95GB ztTjl83fy-85E&5`DkMZcw}>Xnh_K2bAsXry(UCGDERjfv{B99#k`ZBjMM89xTSO1b zh_E;#A=>N`QH2E&R(3>06+d)~=rOrOSQe5HJ>nM86EY&KDM^SPcZ=vr84(twBt%cT zMf8*`B3R9m5IyA@(ZiCgVJS>TWHa(x%p<0+E1r|9hIKRv(bH~A^hX&H7U3jB&$~tR zu8asPcoL%5-6Hx>Mug=*3DHiMh-Q6FMufFP5z(x#xm5f|4UxMa3y&hAqlU!YjgUwE zQ|^AOT1tridA&PC^G5$o;v+11iiqZo{;NwwZL(g&dZ~n{&1GZH`|n9oiLlrzA^NXN zEwacj8%J2F6%j4+yA+Y8!E*OwnO8*AG}vYLFFiv>gf(Ij(b6+qwo%8oWJFkC77=w^ z;}+3VG9s)_ONiW#kR9*H42h*}3DG+)8FJlr84=dSMMUeiyG3-LTs17JONj1s*=v!* zWQN2vMnn`jY=t`!iQFca2+R2rqTAe-=w5jkK`elT=w6rIf7Xj~i4aI2B0B3umxwMH zeYYgEh(Zt%T`<~ZuU#M0E9Bmoww5=e{B#LcoZO z=w)|pboJcdNr(__A|v{(TSW4tAE7ETqSxFal6wttE;6Fm-66VhgNz74G9scIH@H+s zH@3_yI`CT(A0dWIMD)~w*SM?NQwLrv zAwmF{jObdIh#pBwh!8y{A$r7RuRZn0cO^s!J(Cdq@gMF=^xPk1O^diS5z%vhbg5~d zpDQ;ug5E?#&(FQuU5TDw5R}FWp#uoK@ribvt62guP%{|QG^&uh?clCMqhnb_WB_{Q9|^t z&6qvc;yM-`{RnC_5Mb?~s5Tt0N_4RmgVkD+Wv1w}_<$9IZ96}_OGJc-NCOd84DcLS z)FshmD$t$?utXlVsH*DkTPLDIK&6NZ&t0Orf6il4sSuATqQY~RsJ89=g@g*>oFXbb zcZq6ZnLPL-8dO9zv1}|85f^PWu}oG-2qu+L>GNzCs49;-R2l&giz=e3JZg&DQqB9l zJZVQLtB7je?=N$UYT=RcaDqr!5!J#Yb@RqW1sC2fj{^v#l~CQT4=65BE$v<|wH4xU zMN~_>m$|KAdqGe_g)m+bReQn7Zc&|io?Jmh0gI^4JWsa;TvTw|P8k(~h(%P}xYx}E zsyjcCSrjqIBC0z-am}Ll&v{I0D}*qMsP3Pm55O);_23+Nj)Dki5!HipUUl2-|8K|` zsZUD2C8{&en^-EA3en#{ z)xcNr@!TbUD2HL6b}?Tk$WGOAD9YUgb`ACuY&dk$n&kGXBDiDiqW3S!HG zhzieLR&ds3(MQC#!j1ue%=0El;}!Orh^X+~ zC8`IH|DA*iTUA6KUo6uu(=v^^DuLnz!=jPl%<$ zJ{u7gp1Um7{c|3Zm;u{#L{xb064ktwKQ9(bgeVTeri!SrNk~M6=Pprg z+xe{2?AT)@qQZ06sQxCQ!WJbN)!*Es`b0v79ZoW;Pu!xKSk_c8wiPx=iKy`0Wd%=< z43(4@_E(9h@Z2S;Z99Jz2^IF1$*A6RkLoQ66}G0ysNQmmYV8NlOBx3|+eB1&?y`bbcMdkjiKq;Bj*HoZ z)y0H;bs{Rm#pD9jlVN%0g>88vswcxc-OeVgZg1@B6Hys%Zx^Mq`t-3WP()?;^j)B` zuApI0p@_;@L34r1x`c`?i6Sav3DpIvwI4k3HBkn!qftbK=Pvom8X$lTks>N1K)^+* ztPvvEPbs1@B1BxE+P0JB=rR>OwquH@@Z4nux9!{^i8FR{%BXg@73Xa`cSv?SHiKGF zxwqR%Di!vU%BaYFsa}^*VJoVP>h&B@NfpFSRtqZk75w->kwvi)Rz~&lfv$V-Q^|nD zK3W;or|u2NPbUmRfX$P?I;sbVHdBAYDbxSRE;7kYy!5RYIKk4ZV?ss5L-~) z?Gn|j%i@=asIUcDM1|)rQEl7#@f;Bqb});m@Z3GB%_1snfVQC8>>AaMLJ<}APs^xw z6uL(Bsl*J}el4T=)IBqNDwPVmw=JmLmud%+D4U}wHh;^gc6eM@aK}L+D(oG%pgPDk zs*j}#V(Yn#>SOm6{CJXBD(qahpkmtyTxgtGm&K74(rhbid>2vSx$6qWF%-uSPGsIcu`M1|)rQEl7#iC09WA4;6|i{iOUR1?cq7l^2^>0c}rp1VY~ zZRhLK*p8e5A}Tz0jcSKfDx@5cQSESFDw4z*84F}oTipsLaGT76`rG1#jCr+DdYSZr!8;DPhlXyvUOR!HCdJF z4tKUAkzyZIIN8Lyc?wBO#WEqyg@Fqm$AB*hSzl^tKwQR$QSB;EwN)m$#67)U3t<| zoPd-GEmC#>?Excnw8fFwdd&`_@xZB!$oT2do0s;T)SXachg0##54f3V{&EczcG-d0$;^BBA77EyQ0881LsnL;l z1-PnPbzH@r8*O4joGOKEEx<55$Sc*Z#lrEbU<~pkx6OQqN+Hn;(7e*6qbb~A^popx z0{LNp;)9}fy6oVrj@DRgoq@?`++aIeohpU&GCw? z@0_BeDGSCrAr9kE)l;UR(=#5g*uEnY_3RHz+RiR`&NBVy2 z&pYFC2jKuFaTEb>mMy*b0Fif)LCGi+)GD4ku*gAyL?W=Up}Jlwx0UcU7Q!Myq-in; zf?21pTi;k+DcMU!2fS^}wHLzOb}%62W*8OW8pt1U>fR`+y=A|uzASmbfZNYa#k zahP=)c*Z9q$zXcW5Px=&18w9M6KPLvkF-{SzApK}Kq?Q}ADgKHPNN_)o1r9!a*mqN zrp*w>cFXAD)D#ojv>Cxf=HEJr8FH$LrC{w5?B2EZIKZ(gPJ=Six=F=p(`toY&QCRr zmyw99a-{>SAg!EOmfBFPI~s`vLauePQ>Ts3jP08ag+hKiu~4us+VZe2YBG}-7)flZ z3mr;@OnYLf#-@^OT8;{IiujvkM<5=Kwli6@io%T!1wooW6l59~s@Y6Ugp!rPnKd=l zmFWt#M`EpkNEJI+up8&1gerrfWL5A~oSn$bEC;;7_vsCkiu z5GC!YjWAV@=ME%wRo_@s>!_Q*<myU&cPJcE zUZQZDc;RN4XmtCcEfI^RLa|sPKht7X-gUjzq0q?9i9(P3n%<&^B~yV!Ra;dkB5<}< z$J)=VoOu4A&LkUQoDtvTP*5ZeML|dLf|dtEag6AZt~^Hd+4tL-HYguIg#*-zYirh^pW!i9SVb#v?$CEd0`f0Lnh9hxI)!u z^6q9m({jPT-J#&fpNoS3h!=c6t)`)&uAwTF47PLi;byitKbP`ksIQ%NnX+)%PekTK zieD6W#-vWB`SCofc4??}o|T{D&_2i`41#ke>0GvdYrEi@z+|v3kW59g&gdu3a5j5z z>bNM8?CdVF=15|Uf=r&uYObUa1F>xB zMem7hfQ;HG+$AsRe23@RMY!78cz1F?A#FDZUj35Z8g>0_$L#Nf?>YybLJn~h>|4BG zli)(h+kTnhRE!MfnUiKfR&$i@+q`s#)r1B@QY&f}WJP+{N*uJ1rXS_{Wm#1B zIQ-**Q4Y6W@RUW(Cy9h{CIASp{F+V}&s`9n<=C4SJM;h!9st4M*P_g< z9v!G@Xv|4>OmiBDDuXhk-r!IaoO^(x+`dCE${cgH8;nIFS`a6yC)wOy3+&1g!u|rf zK34zL4h6(v3@G4Fc>zZUY8va{d~vO3XLW}opS6!@Yco{W1eY_ZY{Y&PQ%K?T4(FoY1IO!VW3QR z@-mI)4zi%@vG>p%YGEhSb=Q7nwb(5?Z;|)$70>KmikYJoNCK*cR*dY@Ur_>!t zXqD!wNP6Wf7|YP$OIL^ujsuTSjOUI?@&;eJ!bOAUZY|c`{oVs2VVtf6!gr`CMi|et z5^k)nbL{D_I5aqpa00YR@qQF1%luJGL-B%UNXd6&8Tn8Y1UemTWy@?O*jJ$#cAcmX&ivHCVw`ZPLT#U zm<TKn*&V}uz?xs&f zamU$pDA$$k!^htJcug+bUmo2?e+8Bj{@<8~mM|Hw@o|SMmp>h&;oW=)&KX`P# zA@244C+^u$IW6|#Y(SK3(ffMI>IMHnzbxw?whN99dnUU6PLYXlpdl)7{CnM;iLSph zYhTt^J3E!^2v1qme1%9Drze7N*ZvzAVLZ=HI1fv-Zu`?;6$#_0Mi9RA5S=idXD6J+ z6Jl56y6xK!6A9y7ND%(zkp|)Ihq)k}yInA4;j%kK!Z?Hygx`$wre3)0j;w?mYMtY7 zR#}Ej#9<%v?2SJZ3FE{|5Z-iyP8iQYxS%Drb}@DZ$Qu#bEht4)I4~2aHs7#8w=R>N zsd!aqARMXc)Z_UrtK}w*q1HD87BVRLuvy=d_Q~Q*PLMm|M!n>CE|q*gD^`L2NfrWP zJ#fG$5RbY^uScKKfr_+UrOz97yf$UgGHG)z&JG2c?|+|n`J!cPb8Z%k%-Q<4BV4xh zp>DB$IH(kafAOqN7|*lwS{75#j&R+*_dFyL#;K?v{L%|LVLZ=DxIPP$+Yz3!XxV-u zVI08 z%YyK|ojPGW&syWg8fRa!9pSR2U-yZGagr?vE8o)z<9SxX4S8|(MUuA^$L50YutyET z7rF43=F!x3+qX+uns7!h2q#9L#`}0X%hKd5$60J6yQZG9aM>$TQ***+9jFt=^XyGs z>%25?N4RY1rB925ar!W7d|!)B7|*j4&cmv0x~5oivf`*?5PtMaI$=D|N;n@^eA6|> zak0iYR~dwVb&5$i?t*acCRo|h3#A-qIK&x*N1tgl^@S|QnIm&GBnKy~bJgXW21V(>2ACIN^9|5dP&WCgJSj)R>1HH(gWQA=dcVE}ig@pFoQE5*>6&6qB#eW%QR9gdOu|}r!uj=aP$Y~~zCn2UG?Q@91>xLhr%l%sOMB{Z zq&NsacDPBH?WuR<>c%WVMH!e&$`Xh3%Rx9b&m_#U#AP9zyUo>fO>w)})Hp01gr90N z3Abl&>O7W*nyx7xDiX%Y>>zyKX(r*J*$L;Pofb9UD-y;r@F0BP}B5&SR;hX-h?yNchdoys6*hgtt_% zgHIf5oR3}Iw539lswp2*swD2sQ@W&%J>3zJVBD*+c3of@E zxwceDL*~hx@SqBlaP}cHTZl^r!l#OT9OZ-~(@esrW@WB?d>~C*DpDfh>p9`dBTd3A zQ%Dx(%6+l9X-kD<&<{Ra@8j{On}o9)^!dz>o3>OW#2Sz1ge%TA2`5}Mb?$SgrY#lH zZ1F@+_{LjI!r5nw`2{e#BnE4D`Ee)CK`FbDM{&BM*$JvL> zhJ2&GVHv$GSPv*Nqy7vNm;N9t-GATMN$=37__YPWYK?FEyC!%&dg#^YLYFEj&*o z{Kktq;iq~pGYFrTop3(0#jS-$h=j+!%$xezEe7EuvJ=k7Be1pbLXq&WH*~_Uo^iQB z_`>Xj^O=}$sgV5D_y1ideBzdG=!CaaWcOF+wfwWSP|{AZw{^nn{&J;JrUg}*9i~#J14xQBKx{iLq6JRONBImyv+$e zo4VTQlk& zExaHr;cPJiPCK2>|5ztj8@rZ;%S?%PC4wD+q_zurZ^or@STeqx?-1~E0WV1-FUdHq zrlz{KW>!@ohnx}zWh9*~IJ;?Up>*WR+n?$U)BT%mhP1IGSDY=QEDnR!mii;2sA+4V zbPPj5uTHq?!s`se>==d&gl+RSG;J-Ejtsf!&;mAx_xc6vh=!g(0BTPh?^_2a8_!b?BBRVTcqBD<$L+crig_Kj`Q3C{ZH zCrpsaS$30TXk9*eWezZZY?oBVNuFQi#WPS^_y_y563}OP@D5I{OkxJ~2&ATMN$>b<&0Nb;5t`{*@ua=ep2I&P$ngBjHQm zlTWn&_4H!KL03QYXGZv?@976BOHq#{#|NSzZNq|aa-AK{wg3BHtyr1HY8_|o!#Ykp zM`beMblM7f^CXp(@25X_k8!vq4{U3&EmXOFW@Vr)*A0Hz^3yu)lc>B|po*99E?&Z^QLQp?8f!cQdu3;?33F@ApSrE4 z(>{V3yoj&yB39;(q)4#f80Y{;DUy^eZX@7{y&{U7UIJtdHfL;$(x+A~taWk>F` zy}x{P2@{fOPkh1(JUUP_YZl8D<~FZTy^!y~DNTf&8o;T0-*`bU(+_^(39~HR!FaY{ z6H)6qb?~I@sGM5s&X3AiYyI}+{aDE=kuEtENLJS(X)@a=Qe`Ghwp!Ot<(gn3vCaJK z)LIYlG6jC4muY%1p3T{sLu+M2<&+)lC0?=vU(-v*vxB+FK$W{R*klLGPUm)qVerj2 z2eYm|_iqzfSI;q0n>q4$?gc-XXLw9H=gf4nmEPk;y_^?SNMx2@-b_6^XqFOXsOwb@ zZTfc45Z0#k4^3umdT6S%G9GRV={v02TO*a-TDZL<*P|gS;(?8wS~L}oCR2$nKz(z* zSPyo=)UIU01Sx&qL32j1;$404tT2unz;h@Ia|?>MWzBq>tbTY=Iv0EPmvltG(Ao_| z>|AUUk*_(tE)i>4Gv99ajrDM$bFbF1-MIbh44ZMdkcq9Vyu2Jo0kzC6FE1~*9w366 zT2X$$QI2iDOhQ?5?24AkRa#=bmSAU^*tOb**3NV@$gvQb90)bvwh$?2&Lr=Cni3K1R5i|P?zuK=TJ#yf=qTqMB7L{!f4_yqW1 z1;1^sMRkjbR2Z(z;8K-AM5}rwaYXb>{8xr6K2!xL}B!o*y_!47qLV$!kfP6rJ zkO$-eTzr#oZ-9^x5@O%q|J1X4dR8kzh`;amwXK=iuBua~PMtb+>eQ)I8rDWT7fyOv zxi;!t7xjuZ67~rHBpP+`7W|@Ib_QHCFEVU089>41<)Pwvu)yk7nW2VNn6|D5B{6-ZD0kn^%0>e!1v_CHZ*(5ty#C4$IlUW)4i$fVlBCY{&eRYJucOLPp(?lm1=p*B#Q9WqM3=oH zJvcV^T0++dNK2L}tgzObobAXWrD}@uC-v(27=e4_5~p{|V7=kR3xlmT`Eado zwdYWA#N)8B#G^s4hD)8+I@-5LhN^n4YJDE1@F=?B8>HxY7~OWi<2Yv>$65cd^GiL> z7H4XRJ@Girk{3PfIGZ1)4((a@u(R30NH#*G=>_N=JlDu?5asFeH)^@YnHsv1i1oM} z3p7W_)<4}!7198y4hp1LJLc7DeO__GO%gsh;a2(k6^=tUoq_c>F=um64|6s@mH1#i z{@lo%O_yJak@tA7vw=CiTXvUsj8t|Ej|_{Rj(K%x9`_Jl#GD>L0f5VO*?}I1;I7-u zoXr~nSFlVMP$P#rhG$K61V}U}(Z=_nGeu}${3r=eG1{C*oz0sFSy1GX({XXXmw3m# zWC0^MMV#t_7u+oQ@y!-#)NhQ)2jzQ6a|~}hkml+=q`As}*LwV(8glM&erbdAY-eid zD(8up^*9&Z<80b+kF)9es~l&e{O(LWCR6dpe%b)~g z$Hbja9`x25R?z6}dr(queNG$UJ^||CyORR&V?ipuJ5%2zQ}M0n^CBRyUUSNZp+m(Z z5B&)1e+lZ}pzFuHFmdOPk^m0@fsGmg5a7_0hd*dEU!<`k_C0cW#}Ka1s}XDqw+T5? zF@neCZ;W6yxnl$$lSwah_m^k4Uagz4m5V?9WdtBeLemCE9O1Np&oxo{ywwOasGAP)X=k?$KTT9 z^g7M39VD&L4-$4VX}0R|EK9sa9m8@(4UXgdg5x-EbetZr+b0|dCoxMx$$6pUILG920Q%#L9mg4VoK5?$a4;{E z-giCXQ8-dFn~;fz9B0#SKE-h+W#U^MXY5Mg^A5p0T3aok@V$D7>%5v&Gc6xnv+V<$dF@Ua~q*W#leA3tuj^XZP$J6S3X z);Qe+GT3T(Nj;33So#i*diBxKa=Fxw=LSc;GM-XxxjH;}dZFqU7pk>Vx#YEza1gi; zR*IEpI8N^d{BgDVLDK6X$@z|Rfox4uRI)YAtXrMOopZ4D=7Tm*U-U!e>CG2i0}lL= zaO;Ow#8+ij}YF%E~0c*2K%#bme7&aRJQifCnA$-$nvK3oyAiLR>=R&zkxCfm*HZP1T@bP3B19nd@sRIDcskm0nQqI`>3ug(?!POCRQAF8&6{oTH#}}PAqV`W8vM?=FyP>kXk;)7 z+le2{tM6js%{9negmK<4LE^jLnHpLrwWup$9f6S;nb3}lj)%qDj~yZ5g0UY5e!b2k zWykrVgoE!dI#WYmaGYOqoX^qcU()Aa(C44i=O5AMm+A9M^!a)E{4@IeQwLU`tH}^Y zLJF3jA#A8T@x&8Pe2VgXl0H8{pI@ZUKcUY*q|eU~go_1)&6^;@fb(Y^hb%c)IZn^h zgq+*-KLHn08+!GXuXLPG~AoG${8%f#D>pe9fRBJv$&M84C86r1jxk{G<o2wf7IkD{;b`vO`$Z4p^1S-A(20 zR^|2pul%ID!{BZS^79s=8*Y;X`g)&lchO5e^fRW5Hsup)Xhv~4tA~+dnteP<{JLND z5+1XCxGeTy!;3h(t?kuzqczvb)(i^nVP~j4qCbmv={@W$+Eb9+XeV_5{@on5d(i)x zRGS|A;_IkQ)cMcJZ`1a4n_D*OM`3^sZ|W04;uzSD?rbUTqR?Q zl*vmCFNoE92=uvx$BB9YNj{e>&?c&ShxNWJ+zO+l8YGd@-pL|jrSa1m682hTO1*|H zDSE88P4gDDR(X^RRt@B5s&{dfx9+ZbcPEh-#GbfaM}Y&Gs9?+!C>XTwiwCof`hKpN z#c5fA$#C692OAj>tOf=u3X_&BN<LFCerC-O9QlsH@p@7T314^Rn=fI$}CzuIOhj7KhQ18CX2c>Ol*JIrA6}H zF*n#|A&7c31neEz5SDmQ3pL?sjp)aVnl*?fVNy9QiK3c8jidKqX7v`uImDz=CjW~} z!8fjUxY%(v-MS8%lwcX!YVWSg%{$a3C5WbCVOOYN7R>mU`+v z*k9(4c+=uT&|4;muOhb6RWVU}gBP0~CLHxz)Y9O^IBZ8%u6qMipZDTc6xMwM1XavO zUTXns11zZro1Woy@IyLvE<9~O!i^-ITy3?Rys1#>Okdz$BU$L4?$yJP&x}X}$qSlSmL$Z9u~$HS5ZzLu&@V)e6Ig9@Vhb z_^p^%2N$^(HCS`_(R~UYs#^4G)i6k+u#uXZz;6v+)AC;x0ed!Z*K$yeR$AmBfafg6 zx%@u6acU@boVWBiH#(K!O1;W=?Hb)tuIwD$z1th{%H^T*u(zAntE1(5Wt7j&)pm`H zjFxv*cJW%ZGBPqeGFsj}Tpk_X$*YkAhY{>X-HY|rW9yyGSg~xbhFD((j#GibtJhg{ zoZcIUcMr`~d3Cf}Dj%uvoweONE7kJux>wyjI=XZB=%`m7ovT*rqh5XI zuDPAN=62L}?k?BszT;f}zW?!3n)??Vr~FGB$}igRj&(iGx)=5IIB&1~#4Eox{i-)l z{np0{>ub9TNA~>pr+sygbK)5ZV^?yCy_loy^ z^uzD@<{cLu>AUTcKfm#%dpDikwDBe1DF4k>gTMFFAAHKw<{mqG%f62s{z~a*cb1=b zqW!5;5B~l8KOP@={|$%v;fI@_I9l2?`HpY@>TkU8CyzepefyvI`@a?Z%Z=B*@^#O6 z*5^0=_D8-j{NKLtjX(VLU-L+^j_t?Un9f9==4@bC?v`m2xL^VlWt`LTUxAHJ#Q`paJVwEoMt zf8hrajej}!Y`{0%@c(;D&qxU~?`L8|Y4S)Bdhkxnv_rLga2l}So zHRk^H&wb;ZNg7Zo6{V zWB>A{?`-(R(f{lE>s~lJ{QAFq^L#>J6fAq-G z7x+JX`jL-Tzx^}s`KNdP#7|xH{?8@7GvE6ClKb~hoBUR3^yTd5_WpZt*&{by`I+xO z`u#&UKQeRZvA=uI_ikmscGZi$)<0gn`{W09A9%}kpV)fw@Sf@9rSE;$Yd`R@51oF_ z-(2t{(tX$$HLQ}`rTjr^)0=R9lq}; zw*6zf{l~kayT16Y@*Q8Uz4i~j^Vctb?)r-!dtr6`@7{3Dga7*ZSA73}OnvUt-@IbO zAHD10=e;jD^6J?~y{+H+>>vH)t8e`3qotk)UjEGf-~IXr{I5DM`PA=UGVs;!Pv7vW ze|y`*M}PJ?SNzGh@4EMq5B_m~&v#xh@xk!9U%LE;;w!J-z3!n0d(M36!(aKrz`*uX zAAj$7%entEzf&E)^uR6kYiGvlSB`!41%LL@H+=X@xBbz_zxRimzH#L*K5usFD-S&5 zYoEIDQy1O(oKL*r)ze@5#Q%QNrtQgzC*FAa^7l;K^@_&WcOU<6XRi9^+wS}4@|Rv; z*mU}H@4Ni1@p~US@ONK%%gC2c{LI(BeZ`-gzVlbUd-YGdLx1(tulw{Qdg50OzV8=4 zwExR}*Ie;?XTLH!`?YsgFR%9e%NL&WtdBh7D_1=Gia+?xr~l1w9D8f~-OrevebWyx;&vL2eYH%YHM zSgv|{uqj$kS_PfufCGDz z;f3L$;bB>Lo%6d_I?l(hq*nE)ieL(auNQ!ABw(@MvVajL7ZI>l%f|NFb!kj4raVy+ zw=mCxz^k2o}NP`~7(z zhAw5$nGVB*?VC6^+BTUSr-w*KL?m+FtDB^o1J1owH{)7R$TTBGq(fmi-{3`%ntF$h&j^Z5S27e+Z8&-}wc(z8ET_(a zMLO&+q_LYox%jWYB`u3 zJqIQyKk{4TeEPgq_#%iarFOuR(sB%wQ;@WZi+n{(6A1NI%d0M$^(+JoCZxL?VRcc; z1DUTi=y_V=K}NM&t-;1n(t=}d#PvcCPD8C$E96BOG<<7?2^?BUD`kiv9PrNAp|F;L zNR|c>g#}h;(a2!4)rbe9c&Rnm^3sc2Yu_!5TlGONG7>toFGuM(dgKLFEqC+s1UTC? zXUr~Gq-N`hykK4f!7AFy(4L!brK}h~mQJtxjf6*ouz$4!KhY~f*z+tfG8;dg6g#rw z%tdF`h8NBA&deF~BwS-4h1seTSlzaSz)WFfK?9@KqPEOtsOZOj+(BvBIxP?~Pr@S@ zBvgNANZshdgL%mu|nk~I-&xJAS|JkKTzNN5%CaFqMYSPx0QKGF^ z^V=9{)v#$TGN>}Iwp1HzMZE5-&1^wadM^)QDBQ6Ch{9&5fkQycO{!PQg#)g1!-FJ* zBF2NS*NUIS*@v)fam1#=*JPe&!%+dN4S7^VS*Nab9Oo~EiK6d!g$&T>p z``fRJ-|(OM1PFq9XL_6mHpA!jiML=eB2XPm?}lSdfEF$~&ZhfsSzKs1&Zh6giwm^S zzy|PLom*kptjcVvbH`zSyJ?%;@nT5`Cn%Oc(k5(~&yizM%!C@I9He;6{6J)dR~Um= z*w!uE*l`{wyvCOOWPy>DJnLK5r4A7lQYMUOiUeM?y_(dXp^TvjA~sJxkKVf#bUO+;8z#evfpU1 zIS!n8jroB>USca@AD@^$bl`Y}xdLW7po^vQl z9kK50c2I;m3Tj*{(si zV{aZ~#;>zJc5={fvAQ4eWv|gtm5>(=tNTHXEidqh(?}REsNprs#+mE(vsyTQh8TaI zEqhVm2lLE5LUKV5cG~7IsIgNI+d+*<7Z7BZ*y5)=k=AS*cWFkO=Np&`J)= zgMJhz6SZ2zPD%*6y4gKjw`|?gy?u~h(vfq#VBkPln6|>l5dI3|su6p(ZaK?%Bj%lL zKPJ0DNG3R)Xp-rsH^U{gwjM^ya4iG@sEhH^uao#xU03yjlvwf;kigx#;dN9)i-hf zKFIa{Qw5jJO1`78v@)!dHV1B7bVUr~bO1^^}3t^)M()j^Pc(WBoUbMpI+VCaR zOmq|dDaL}K2`09J&md61N;PboGx{uIh>lmv%{bK)ew{jE1;f*8MBJ;b&@knv{WysS zfLOqe-a5d-WPwM^e$1IaAA}KSwRWokpCmsF&Tn99{uNC~k4&P_L7r3>h)IYKh%G@O z$ugP-@C&X5F*0=_1d?Xi9@*q$5subSc0XW;j~-%TqLTu_59%T7bH$vBx>m+m!LCDM z?Di{w6SW$;QnrZ4)O#S5>dho1#AOCKJFjtg%O37Fwk^akzPD~U3pb6WelLTO(Uwc5~9E%pP?*1UducCo>O#4APZ?0i1N+;B1H{V;Qv7Nw4|Ev1-YuFYJ` z3v9D_@|3Z3rgJJ#>FnJ!sC2HbDpWdKz7CbnldnXj^Q>Kq%9J~Y8kNbt20bcMV$F(F zrriIpN&QD@Qd<5S1?WeoNIfZ3DF`&->-nFdNv%oMNzbX|C#~nyYWHasE&I<`kj5I} zyix}$W7fRSpq?w*KiPDrG|7iDct7bhE5ADz5Ux)?5L*>eDjHms6oJ9Uy8wR#^P~#D4%~O-dS;MdLAm+%V{v`{3 zEX@cp^UMj4s@G`n8Y|EN4rJCVE9tGw8h*gpO4v5$v$+OG2j1I;4FgLzR}^P)*yMu& zUmmQ7jT(>05=SflMuTt@uVa=hcnJ$QuK~;)*X9jrpaU9y-729MS+v07wE^720O>c#Hk&n)_s-T=x@w^3I5=>y%PMF7H#8|=+9pMBt@~exiU|QdIa;(7v z>&+}HvP%DKKdefF+N=a9c*bH5rcku&gjengQJ`|x(7GEjyo87`$LIZk%vk41l0i+A zHIO8y1+;9xfTmYi2Q9OWCM(}b?EY|LwW1b|spt@ow=599ywx>s3Tyn91 zmk$lM8lP*=GnaKf0Yr^=CbV?RA z-;KZT#*0#NIzic)QUlv6iFndYnFJ{+l|I?-fSU~73(vEWhJmbE3txV z2}~mjX%f^vwk%)}0d0iT6qNA8fGyy_bs%NVHg=B}7ni(7o8Lp`VZ<24p}nLX8&N_+ zy#+&#AIz(omLsnPS3TMZVfT#HLUyK9DxGCvP^7-J0Mg%G;3=}9ynu~oFbTs3tCLZx z7AHmcF^szfn2DGtSlR;1Zu}nb`1x)8S|eSlrZ!c z1h~E9Y^1C#_bLOPZOp4DJYpkdb}cKHDzUJ1#+XyL$83)CfQ_)2gBJ0C+&L5cj;Xp4 z2J?&uVS9eT^few5-%129_lTKfsu(L|AGM}>FR>;DTVfC_tRw`>bxM~^wIZ7qJ|-2$ zbNP%3lP+3o%P>qhf?A4d*RcwjDH$^YDp!ON`(0>QJ%FO^fB_Vr_|s@ zNOkQ>m{*wesMbQ{#eCca7YGcc*tl>M4-FkZJTpBrF>~|8(8$iA@=$r-M5S1{K%CD3 zt)mg!#35tVnp}F*tO9q@H4yyJ@bSYl2lnloxp`uEbVo;P-1F;!b3kJq&4G1Qo`Rid z%CoU2qQ;)BTeb-wNMnA5%jgkoEVze`&lJHZ#pw#T1bw@0753{Z*q|{(5*vzXQbEPg z+_pNi>AW4S*ha%$fwB?Y@nlEv&L;_iKAhJA4#$oRF(+rH4~g!+^GVv>7KTGl5^`o} zIFoo$-RF&(AS5_d%GBaSJ6QQnp8d%tlL?@l{aM4hC-eV1V@Y7ZOq; zM+&^bt_yk;G4I^yQMMlty&>3gl*ufI2tzx|JI8kHDwoB_Sfx@~LzOTdjZaKWOq?h1 za{2s$gI5`NRc`K%yA?s10XAA1E$t}nuzMh#)7=9l?zz^Gv?G5Ei0Phvaf31yUaE9F z;ip%z^|}wd^A)7eJzE(EGXZd5AG}zWgAVt?4Px3<2VxL-&9Kty4*IKbqwTJ*&n+lD z@4Qcau!_qT!Z=ZbL2GhdvHnjyqQZtWvNSZ#jjVMdC4CM7l(WzNoa0q2UaH#mSTo`tB~#e@}jd6@@E1c9$xZ zA@z@pNUI8qj?+Tc(HY5PyDO#2?x9j;ba!cpq#m897kbn}R zA@Oz%#M__dFIS~_8-jRy#>Q>1eW?Y;B*k7#Zuej()XR?Pu$}PerqGLO^ct2X(w?jY zcJd?}Yk5)3nX5t!!3&;8b0{}B&l8u;&Sq>#rV1`&TVyIwuXDl6#4fO{28i`}2DW^e z2N@2%-aH=^F39JGe{6C7M5{IwfQqH z$eaS-Cj(&>_ma18J9hie3LDb+P`TWUS<^c`K4P2dh%teOaUVTdFg?u*RyPVHuz|5^ z7SJ|>X@0|m(`B(9Mn&l(PR{6I8y3lVSU;7KQ8i+C)kesLuop%9Da`LAxxbw`OKVd} z>TIGL3!T;-JL4|$6?e>a_b``iw)Fe#9$6gfNnasVytvo3sN?qMaZ3)H6BlO))CIg` z!+g-4Tp|V$8Pvu{a!F-b@A}*W*wb?R!2{da$+0B#qR3leh9={JCNTdfn&9_Yc9t4p zm2q9X=|W?o;MOf&+F0XDrkQ74Tq6-9wUE9SY}9P}d|>v{&TG>iQ(7~fSAJJ~vm2%TMo;cq|~0Wmpj+XlA=GR%7o zC7R+f>7$6iZSv?2UWt7$Mq7_3nGy;j!=SawBip15;6^5^Ss2yJOxeu0Df7Ib2W2_Q z#_kR0Xs=2zrxFLkwrOl*V$%rby(o-JiYS95kFz*IpYK2>Tn>1YLQhOj<9#Q^&Wf}u zl1n+QZ>6mO%iJQ4+d#rqqXz3MbRbt!f$OMICFYi*xa#(^u${Ep$vABxE2+q4i+f#o zMw9>UwzKF_P#m!zg{uIMnttFlK>MyuQ@kYGC1Uu|b`0W4oqwaW^)y9ZRSPv|Ev?Bx znO2AbtCMUj39C_~&Q1y!af=f~7BX)rBy^tU1nHdc|ulyZ?T6%4|C^b`BsE zKFsaM(FfWjxL^R|%=H=#w;!h|Yy^xPv|BA(VoO6f`-Fkmu%U)qeG4Yv%gX&qGSUtm zG&FaT_IjX1S>WMiBL;#|_xjvZ!KqF`G|p%nJj;4&3(npz$Q5JRO#;Pi{bt9R8l&E8 zsYYDN)V`qJ6--g7V7B9=us~aAs>{$nixbOim%%n2Jgs zX%yv@d^9)!j~!#O5Q?e{Mx7a1`B9P6Q?59~$lSGrW0ob;9VbG34{D5U$)!h^9f27K z^+hj3rUHndtI^y8m_v)RbxuzO$D~z!%j)@ zk$!D~QGL6Hz}r6nUv|da&SB3^PDwLo9*_f$)m;LdqXp96OD+sp619a+ zWt&%X@~I^b0TAAtWFVS~=h<3FAe_Rqa${SXB>$04Qep)Swj`A&rBo`1F_j^wUq*zN z7zxILYT`IGl8!59*HJRf3|J%o^-Mv>aiuCiE}lZroB1F;)C7YJm*YK|9zLf!K?IoH zBX!%66aaY{NOu^g+`C2NX!#VKzH+nI33o{<}NGs$|S+9|*oZdIt5k!J&S&u_d9 zm*Xx2E@gDi@Q8aVnB2a^SuG4WAroE>s(;h7X_qF3B zY}(enf4KVR$-4LG%f;Tx2&{WK_myDl_!0{S&bfST>y~X%7$&7=(5{vc9I)M@1Myv! z{i~Q5?B!U-H7{48bW3yI;vikhclVsPcy|BWdF7F+g4E#jik&(qkPzFARt8k-YV3T>KU9bD68TpZ_R66fD({9GM zlQ)o>s7#HbxU}x?n?8I{Wzi6XMjcNEvL=-Q&D&2WAcWm?%mAg32_lVVMz&26HCu?} zrMzygs<=gOV;DF`<<%d>y=J{ii_`v2bQf(kNr8CA(F7= zSL1OpXAX$kM8n3LyctF-DYK~xG z=v#QgqS zcfMe0;V9p6%kEvlO4wRPGgKQDsC^4w0!YP5xjejcxH4ScUEVp2Mz}jhcI+q*@7OUy z@|T@Z$JcPC0<2&oOGDo?>`c9eAwM65?H2krTk-J)1W!TL!(~+gSWC4U7rrNS3}eAt zqCr?{5+0?@9>j_8Cgay zB1~(<#?rp95k^O8Yf5D?`0wWluO^c%glXB&>t4H&m^lO2Q<{MuE-lbbiGptzJtzYw zo3dWZFZnIMzETRKdAY-~ZJSyy%MIibI~K;VkMpp!n;(y1uAFP|0XipB#NOBd!x2h9 zm>&R}@kZD}lqu5!;gzsY>`0saXvi9^BV=xyBkgN|wX$^!?QQ@C1=OQKm9wHkI>cXI z%-j$+6Z!QOmo#0Jvfn|qV|^4wNpt}1^@;V#jF>2=ki}H7hZXFUJ^dv{=Z-@emd~Jo z@McS%-ymM07*=$BTr5$?@gvx12gMO3Q3LA}v6EtUPd$vPToB_P8sX_@h9~Jf;7o88 zzP-k>x1x?ftNI3@_Xo-&L{>GpGV?18;q7jnY#7YN`ACon)+vRy?1cj380D;4_ z7u3S$ehPqv18M2h6Rk$*)o416>vSg4qkHMh26vlsq=uOQEQ{jkbYZf_gTzlTXXn93 z6PVk%W`XRS?e-@r9Z)?*tGdHta`AR36@d94k)mxhZT@Xf&u0_PYR&Nl&i1!!-SDF%yY)n2Y;V#m%!$^Tvv;5e=1N1W${FP#XfDlA(y z);GwCd)eLnC@GGE(8xgXBVo{rcuZG962hn~)!!|Ia!7MIaHH_AuGda5pM>qC6#4Z5 z>(8)J!z(oaF!+qolx7((SYcH%tEfdP5XyPXwq+NGAyI)!&`CL>;U%N zF9_xX?p?V+Pn{~&21_oR6^rhi%}e+K>FpYre{=R~#Kob<4~Z&n_oA4PJ@1lYCv;ZX zIJYr276#(%?SUwQ#wZ$}K?rU_a-k!1Tx?0p{XIo3+lt%82uz+vg65(}wNX61*(`gF z0y+wbP0GL6SY~z4Z}8ffa5^{;kx6(P8Rf{YiSVFshVH4L#+PUw9%lvl6a3YYXSyxo zNQi9mFXYVWuGMHR{D~fL?@HT}q@`v0#F10c4W|MtCT0iuLD^M_FWFsDU;ddQ{&YK# z1B7VQfp8bPF8j4)fi=Bokw@&5YayLab72P+8gA^*!>MnXlQ^JIn$rAX=4D}*QWLlg zI3m49jNPhNSm*_ZN&`AMs49!=RnlygvatQ_*Ok@qDrJS$c0cgEZ8QAY31KrFSrj(I z7r-NOqR{P}*Fm2f`X1E{7@rwu-~$ zfHCH4SG5DD{p9GadgAGDGRyk7=@lutCr-D6Tf#Y3n1P7G_5=+i(K=T5Ps8d)uPA(h ze1Yy16>5>Ahg97^EvexL=N5twxYxQ$aAgJv_FTF-`oRiO*xlu4OI3sPcMb|=uP_cz#IjE}K$80XVcd>0@Eyv9;yIpwYvdS>d7@69X zzHZJA_)>!>fdK0YIcCcqRoQ125C=d7!BKBnnN>!S-N3K$B|6$cJ6HOAf_=Dx(Gd>v zPP1!LGFq3h+=mG@EM+qV_O+vlsJdXvr0Vga>Vgl8LOT-C3pz_HD(Om70HkNLXy7)p z&`KG=)B6hWRyD*p-f8u))=3@4Xe-UOXGl{>msDl#u#&}6TUsHk_reNly|AsB$Kj@~ zx?QXmCW4wV5hx>uAHYWy&ud=Zjl4RDw$62OfV%X;S=%`)mK{5>-_Q?%gf!8e>Dg)dExX8ljP{hIRD)(gl_yP|O z2rqZ_a%$pEE6da*{PR@W&F!WaV2XpiP=GdxlkvfJqp`A2gbd&~8K}xl#`}-V;OJfh z+x4jgk{T;PHTNY&d`tsU`KNizlOsub^kTGksR>D4@k62lY#}nWxZk%)KHbdzjb673 z;Lk(c7V{?p|MbxQ&>j>gqQ-%sDkOp;5MdWa8E|5B91g4Y%m5Rb+9$HAwypS3L}=r{ zN=Gp}&nihcxT+8ndjSW-s9RauE4XRpMBt-I8E(JbYxwXoo>>VJ&mKmZZD6ZHqy9i% z%+nc7g^Wp?^5;clGOMJNV#mWY&rgfvPBo>{TO}w$|6yFD1H#+Xq7>LVCgypN%p^7! zSXL_%gBS}IP%C+VxE#Rxk)H}$N&i>Xz&sIP`of&hv;dly(<#OyaVT6@gy@9Ao1P}M zTd!O{_%R)x#G$}B#EL6WEDPh2X3fdwWmZu!DVaHev4R31x2FqboI@zcYUSAj@mD`$ z6dU(;5vW8?Al5Rt^PHdB2~r;Bw1ml&?;U4_6xwP@q&sa; z9L`(A(PNyk6CoRMmRcO(ArHV+J2jVDr!2%Ii)&0}bBIUvOXNbZKDlzCXoYHvPOW9B z#rF6T#u%pV$H~bcjMO3sUl&AE041*WI~!d&XnV&6U>vkc;p?uXX(|_!XToWWi!GvT`Wlag1A>fYxJ}+i)CJ&KoGH!|D%5|S2g_5Z zqR-=4vtZ5hJNyl_M8vCe;Bf|Mr6s7lhh=0cSwt=fq@160J5mt`yC_G2+kfFT zNYP{}(&8cCQULSh`86fAzH#@klj#{@_JTngoGlUE@ZiAEK^ZmnNxrKnzxF^P^ zkRpTXrDe-DREbWrQm{b8T361IIw?Ks&p!eJjT;^Cq;v2HW;oCA4LF^Ezzh^eH{HUN zogkZ(F%@K!<*+@t+(Dh`Iq8fi(uhnJ@#MxyM=@!wOTQN;0a;f^k{o{Bk}YFG3W>D- zYBelv%#b4_U28f^Zdz_R@RMcpuqw4|MVg<)B%-#!wNR0<{$cMF%9c{ERp=U%)s{ah zFGhro2kR@Sg7VCBjgDO@C5sBA8!X$FE@=d*AT#Po7h@+27SUNDovMJkeJ*qRT_)EC zsrpr(wEajy$YxKiY)dfD%0w09K29fvR%s-6eZx|A&l zI!eZ5P%H*yQM8JS`JZf#T2gcrR#77Be$-s{BF%VOf1vVOnsk(x4!(Kih2|^N3)%!2 zXKvGP#dDkv-e*$0sF~?bYk(SCtF`{g+kVied+D(!P4#q&K{H~r5ak$|-6Oj_4NrBC zV1X1bOTMGAsPkE!uY5{?lme5s4C^ekZEy0Jo>VY08BABH45&o&f+?>gfRdFui-Ax` zn}bu>%AI&E7`xI=5J6DT9!lc9S**y&;;J@-o^?@Fy-j2Dq~BoY=S+FTKSF2V!gDdV*9ndePFbkybT1C zdd#0|_*LPZ%VQ{Gps|8#%xkL0?Nqg4n0{$nkPW1iZQ7auarJ~Kzt+i9No*O}&2Ura z+$pop1kD!7fS}o;O~;hUW9>E)YCGiXw74+?%C2b_b8&+bwpzzr<3TC>THqH_Qei(% zvVtL!4o1;e0Gh?UF6aPLt=lhydZ==&qe3_sBI}sjrFaQ`G6ZO?wO7L+@v6xhD&Hq^ z+I8E7bE;;{z1fRum@>w)6tU?DnL*plW3=?QhfO{?vxPBp=(1`%nIc!5t6Caw=s&f2 zN5yo!mi(?mW;6IYd(9Olj8rakt{{==8n!C@)O;?&y%@wgSOYW^B{U&2lZC2ZV4^_f zx3I4umD=K7H)y~|ehmx)6l5_liA&{(6nWqbLF6xGo$p|k+`(h;`{AM|p=Gg?9FY+K zYJ!ss99Pem$`-0Wb-V9V4SS%TfJesAVPV;AeW|(84 zjbVn(+qLe{!K^KCu}gz%tWL7AD5%9r#2P%9PZq{cvVzKp#3T&bP23_k%ZAEqmi$)7 z-HDs_?LTnv(9M&#+A%gtU zgBJV2>UY-Krj%P!c}b(zPI_?p!}ar7N4R^#IonNHc3NQ6AK2mo?RlNTydr47R} z4=Rr7Lwa$q+wySZ0CD~}bA7~5g|+Y8@Ke#6N`7rT2jZ++dlS7>2Jozi3fBndedtG2 zqqPcvKVN3Cz!c-7E6o^|S7z5)JU%4Gt5L%BX0mZLF^Oi{NO4{Y6P?&N5lgS>Je!NwB7^FxMP!=RA$6$JQe z*^rdK6cw!?5ic>fxL4?Hgs9l*65~f;cYLMAk0S7-;^>0tnAGCpFb{x^3^}y2?e#DQ9nB837Tor z2qH`}E8NOgG%0a4m!8UuiX#Y+WqN^?>V@m57X*>zURuU*l4*0CM5z{^Pg6RH-Qbw- z&{>Mm3Kg}>sC)S&8>2vhl9+w&DIg-^Yq>$Y(;y`U2F1&^m{AVF3>;Sl!o#D4m$ZMb zf`VA%(Uo&Q5DI{U!J)*q#zCTz>IGa@sdPqrXXiY+qJ!&2#BF-7?Fbme;+j%9z}Q|k zTDH_LTK&koO+}V6+qFw@BKZg?BF}boFSSdIYPCTo27?mE+gNXJFL`V$7g!N82C){r z+6q#QI}Z5>-JB#X@|scOOv;NXuPQ`Y?gVf72x-MQEr;VNuSzEh8!HpFrXTom!Xt8p zGcw%T7SnPz62dbD|D-d6@WiD3|6xAj7cU7T%G7yc)7v= zYK-`bi|wd>x~X*8mpD&3y~EY9R#6`*E@}QU2Eb(zK}9$YDd#GQ`JR>Y=Xa zGF9zW< z9YICl={YavhN|NDk_9Z)NeAhK7mTwMmDWJE4}IxQkmPaOfv8X*Ay^iXn(QrOa^2RW z&J2otuY01t)FSL0mgl{lB{i~yBabriyr0il5@L-VQaBpV2Ar= zeTpM5lrpYz>7gwXQNsnmM1xDN@-)d20(QSz`yO&UT{!l-S4mOnU{{O>930Wv3^i>b zaW3wvtMDEFuV%0O+fxihE{wmGq1|5GNP2jwA!TeD9wowu#8I?bqEUwu`-g&KW*}m6E6;J$i*LNOlo;3)5T&$ zXjEj;QHw*FKGX85-$SFBr( zw40VoDv=Ff+_EcLEDA?FHit2RVIN$8qvSf2?`IO$OcKq`+D1T81#r&RA!)2!VgM4L z$T2!fW>q)pZB1&oT-_2ffGR0tb+v*=S;|%>Yb!mk^OOqJ(Q}B$<0mT?%`>uqj-95Z zMMfG-@i_M8Q}ROhn^f{lq`uS$H?P%^!&I^wS@Cl`x*3&6YIKGm4! z7OGmeUh}iWH~*L^q_i-Fbe=-RioA1mR;Un@DY;0oy4V>pd5`bjxrgE@jPKsHN9pO~ zyNCCPnQVM_MNK+N6Yq0RRc<;-`?3V7xVKP&3~ACU`iTtXCiz_0?0q<#Cv%*lC?oPP z_j;+@??vbYNHt+~lRYZb6VYT%ss~t~dsm+b7ji#oA@|eFdp|-$^q(rY>5DLkUb^r& zbE$|j`{K?ssmUA;=LM~@6^=8PDzM8)9c;BSK*yEW6`9Z#q(M^78@P1jtjtXA}^3`to?371q(nl7>jK&6@^QL#sHLB6wY=Tid~6gN8^wx)Gh==;+S!X!@#`)$X;aMvY=k9u3n*mh&r47u8T%R|K3%+2o9h zs@V)qQ@GlQiR^5_iy6W$qCKqM@Ztp~S~Q1yWNdS;>*G!bMAvCYyhck8g}Y^eVEd*I zQ^+F$UpZk3ks#9Ybb7tNVrYm^W0GPIJ<3W_N6+I_r8JL`X4L z8KtWkPv0(L7=Xh55Z77)LIel3Kx~&&la@s#=5D8eS^CJ7u~bQHZHuImIAZf$%Cn3a zQq6^COSOZkFRbl*)0Yb6wOxcXM_ew^P`cx*9VBR{EvCgCn&+fUiOnp8?M4j&pu6y4|Bwm)3ZvP2bd}>?++X#I!s!B6$0DuTk9VdW*CLj5&=QQS#I5w=tDS zv8E+mx_1Q1joW}^)j3zCXys`#j@vxicSOvl9pMF1c=?nUdqc&&?!F`12i3OYV&5N5*H&M58uT9h|3_^9dhx1rKA3 z3|EzkLpS~l5$t&U-Z%_c- z9*sy)u1Wc@hfaC{)X^a+9jn_-g%9+(cVz{ed-ut5arf+Xu!qRiOxNzPX12A>4J=L& zSGFB!wc7MX=jasLqq^G>l}X1#YfiEk2slM??j~s+fTgq=H8p1?7da(T-4^vFVFZF} z&_6WrjQ%m@B?wuko!PYELm4&HT$xf0(v!c`WI!Dl8@kY@&%%DZAnFaH^p&OhEeI(y zks?~Q>}kprPZf5soe|ZkaeE|WO*Az-Pu0VAV0l(3QW^m*D4e6LrP{e#AEh!v`4pH_ z6QS2C3a3P>TxoReSrvRs`449Mb=7T!^j?5ANkamVpW`{**j7bg19Gs76GXZM~gl@!k4k^7JFfG z505cP1QLWPr5h1l*L;Qy94YVp)E+{qanl(r$|%ZNJw8=Xv`rq!mr+f-7tL7$DC>0! zYKKOeN|hnjOf|-}EtM}V3?%hB7n!LtN_SF+Wm1XR0AGmWWw7WL$IImCh}C71WY?Q3 zmk6{q|JgPb-G?~O5GJ^Te02}6F0#j7+E~I-x^)e(L^vVH(3NWSlAe161CTeY;&Ua* zwX&qt-qizltLW9a_5#xav&5gMk#-;OWp#^`u;B?2+V7*K!5%P|S&=;xQBYi!kuvN+dW@*=w-)6#gROLrFf~-i6HBFV*YGzN~ zsM|IzGr78;_JKb4)TudQPTejX#PpgRFDVf#M2SQmE=AH55{cAW{~l>T87! zzq%sM#_3B_1tnyXZG^>Rq+p6IjscL*V^;I)buKO>72Pdun7OUoF3ed;Y@(m*?52@6 zT~Z4~vq+UaqN9ss8jJ2P?sdhDM(X@v_m){gU~)bP=@ySQG-d$TJi$qs;w!7UN<4Cj zt#?-NNUT-AXxSkzO|-XrMf>nbc2t>Ro>nraxHsLo#7zB0LZv4|l~>XR{=UU_Bn|aCOuH-w?3k}D8Kyy=h~zZB8qgH4c7PRXKo{Vwub{9lse_n8GHM}>81f{-H7@pG z>q2*}R@nThXkk^*PrE&%r%d_RC@!G5^9h1QCca1$7sfSb@E>NxPSz}4|k zBjcnyhn{l9nw5lwh64jEhLcs3a-27J-AH!r+7;s50u3Q3dUlVb#FFmu?e>WVgRn3U zKsCZ9C-tyg!3fKnh%(A{ly`K@r@7}<@aUnXNSGrhLB;eUAqRdJKBNf$XmzdKY_61W z_A$i$Q8FR`1tGa1BMmcZm$Y0;%q)7Wy-|AdT6NO3smNjo>t{FHy<$$=c3m(d zs>3#j$F#4(E`F=h>aky|zkt#ae0AZrE^6Oi1sTSAa`)~6g3;srkE1qfrj zy&!*Y?`KL|Hv0zD8lgiOyD=WQhePRPTtR|vcbcR z9P@iVdAo5H&4auV^YPTwnrd?zH@*0!)?)x=G+MzNR<_=8WD#s?lMkw}I8trDb;sOU zaV%W#QGkMjdbLcivrnCT~ zhs-{j?iPxhwQ9A%9$22%C>o5+mCo{`shqIhp(=}L|@;gEb{{-Pv8tDYDQix=D9)sIMpravaUtsa1Fe@>4fGsch zkZ>`%UN(8c=2mb?Jj`Bk;x&ZISn49Bayw7=Tc&sRPk~6C`y^}V8_N={xGAvN4+g8wa_Eo5-vn8>$!gPo)fUMwaS;T*f+H+*^=&x~||! z_E=aK^zQ+i+Q9OI}Z3%VRIZoA;}{NcW!CMH^xv z%*>9vjVVOg`7)Pklp2lc-7i~RKo8Nd>#h){2AjC+MrcLi>gKgeSrM|J_ksqBZV`^S z&^}b3h(&JJuVRUso)OIG?^KDpPaohZRbgi7hrN2SX_Z@%oSZU=W|B==3*~lKHUON^ zx~+X(tq|I3y|oUQRqFsV;7PNz7tUfOKhE6Db%3;7NMWUb*$S~;4iVATR!SUg(iNg0 zZW+G68P@s-OX-76c%*NDwF#FpKgvO!+N_~>^dXv@+QREJB%2{_wlYN#u#w!RR>wgE zd&BRvu5O$%`cb~!FU>6M4DKV=?H3op?m<*#^AbcsfG&Cj&xx252Gx{%A&9d!T=j4x zOC9#Cvc&4POS)HC46S`qTRa%lQlbI#aGG}Nl9w85ASl|#q5(?}) zFts7LB@xO>H6E$Dl_f_qkKmFHaB_S2`W$TRhAT$~Qy#%E#VuaMz#VQP_Dx=t zLug~7*x_(~pSUQElI*D}l_77slDRu1d$wTb7@)c`mub^WdZ5wcEC8MJ4(1h(8G9pk z=T_qaq6#Fn5c%lGs2x}~MA;qY*#7xIi|M{KYYyr)VFknxO3~8vmhO#QidsHPYJ=Sx z0Fp&0E*Kn|3{(|R(%!Pvt94VQ4O71@?lqJCqzZ8-p46ru9@QunrcwiumXXddV&XBR zwHA`5FfO*ENnG@r7;uv`{8o2dCY%QX{xLG@<}LJUZa|>wEHk5TdW+2x^QX`Dr3LF?t+Qa zeRQG{b9syDR7oE-+JsQEBcZA@>^PR$ZB_^a$!iEWfiv@v_6v!5wG0flQ>Dl=U4|mMXC>vb^k4XVisR zLwO&&XrKsgtxXdb|TF{ItO<7&(O{F}PiS=`nk6`1eX!|1TIA!i zslZ=4WV6_#k$*$Smf*C8e!SVLP*f*G7P*#H%4L8D*qoe0tgk=?29eRqK?axO&DIdx z3!0VF1ffDhm~SK^C04k}56m)1F`drnmMkHprZw3ZLO{`x>YSyKK-vQ(&az@QgAQn{ zSKfFs_{bJh&!vRDIgpYow#*_%pA}NVoC4YB919_4=op2?bkqO|1t(ijhv-W&pslX# z5H+*|_XEel$Lx;KT4cmF(oz`)NldD$iS+Ue4Dze~H(qoq;2j=SO0-87)3nfFh!|9R zQAuhWo)|BLq+4`tMV$tcNN~@J_*zT_KN6)>ovJdS2}S(^OT~>cH6;i2Z3ai^zBR)S zxq?idRT38&K=6@2xD*5?d{RnmvK>RackJG|YiRcfsBa75X)maS&HcRLbsTQO1@~z< z#LSX|P6U1;Qq%GGa*>uVGc6V1WZKlko#JmX?oqetblGS!s|z70?gzy=^QnnDS%tR3 zGT^EIlQ4+646U31XkUR~BP_3>R)JdM!do0$EVDuw;Sql#gjJkTIS#~Cuf-3B(KMew zaN6{m7^Y%K<&0w6CZ#6Qj)ty!5=>M8X2dSXU8R$=rwV=j_g{P64QI}tI;B(_%l7gg zAQM;WrwGR3za=^+E2t~ZW*zOgrm3S zQC!fA;u1)GA!PpXCuUARR_tp>2q1cyb=}oC3=lmUBWG-oLLJ=Beaf}VBizu z3Q0z(WrjN-#+gfJb*FvYf zB#hVt%)P7cery`tFZQ%V__RK?T%%n5G`Gs2_^C;5$`AbgUcxctW)iPy2Vho~{c0oB z@ndCQERn6?Bu*dTmr^iPDve`G#jk8?Ev(nAYkJ-Cz>a~Dfn5Wm1C_G6K~#a7n!@Cv zLKcc@`w9f2xOb@E{2uPlR6_-+8d5%|rgS>7fB^LXg+?AM;eXsluX$EH#Lyl1?i#36 z1}X!?13LzGYJBlfc2RGi48-W3KJ5j3&Wl=+x6%&UjrKfmRg-XuS0|1fxM^bg*!0Bn zPaHXM_{54sm~>W)gbJ8HG={kX#_IFc=R^UZca;;b@bLkc~~ za?NH(u3^S>tXr8Y#;I7%OayBuW1||D6l#4Z3uq?>>PavTeb;K@`{tX)ce5$JALt&O$*PxmIvY zv#>&B+?qA=v9GWd!dAOYRmdX)mfHoIH#J(>pz0DT~Rd!&a-JQpv@_Nm-Y5E(`m@R!9zL6Pa@w7Ut~yaqYAoOJzu)FB?j| zA&D#7buAk<13ER$l4wuqr0BLo5Wk^t`RmGIW_cp#LyJEN6{+y#2g6}ybZN?8LiLZO z>j_Q)N;s#ckhQO1R%xm`=-e7!(hMjEU`}T$HA9w9kzl&H-?x-;$*z7xAoU3AXg@$5 z;^|0}DILLR0M_P_aiRAkUPW-8G3>$?WPOt3H4fsu9-)n1QrXndA~C(+r)(+W=GI** zm83&fE#$%_i=Xym@*39*7YrAE8^+frZtu5gT3B7Hd8xX?bGITQW+{`H!F< zkb@A*M=*~X04eT~tPW8tE9w-@)Wa&{50inQ1E-*C211lt)fvL!Ue=$^5ih2+s9Y99 zLCIbCX_R2iULa8pXAyQO#u7Svn!OZEIYFR*bJ5U48nxx(b4~^$gu3z9)MAc&!j!#= zaOys_qg7e4MG{a9w{F5ccM&AS)YRhfW~(0S0id;r>S*E*#Vn(T?lx>+wK&Ht-RHoeuF$qD$rApcR#xkmQbr>KyUI1_aeJ@HWQcGE}%;~Bm()$fbAM=pAx5)11@5`mDlSt=$k zm+%z!Y}RFOT%d?B68U5%5XGiEiurI2GTWSv}2@|hTZ1QFp;ckLKHf$CSskuLm zlMvFPwKlm^JMXJBIcE$hU~1qPeL>S)C21W{j5H{)asXwOS9&ctPRK8MfiR>t$K=B` zy=YDNQ{Ez+&a}*v(+t3-#5G=IXZu`agmWQXUYQoAHiEgRnEBsph-=Ge`nT9Azg=qN z$^8IGo-%`haa?t>UA4?zP+}pY_MNlWL>G0H&R}2?4)!!6RB>P?xgy1hCc)-HL!uN9 zX8TJDbZRx}E}g<$G)d9Uu%T#4SFt{ECy7kKW)-*&s@1mARw-n^{tIz?)Wx_{lSfj8 zuU}(fc?T^lbzU{$|KE*wrCX>jSj?zrGYN%g$Wiabq$Z0Uj6!+ON1iEBX1c>q&BfZD zs34{GaY*H|p&Qwvds-kT*hdCO2BP8yZ@qUcn~(yAMJQDC?4FCnqIWy{#@!#rHlXn+`MMj$9MYqlshDr0d^t=s`>HN2`I_-sG2(`#8;??Gd% zDLUC(Fd`o+Hi~&l3Cc164d|Timx@l7e~2!sGlVpFfVqQ%QuI+v#cTVXAH{qk1=*Q9 z=(1UBfu-pp|B+UyOhmrbOCOP?3R674?1vt zir6%FL~Tw>07}7G7g}YfG&I%Mg`rHf!>Kxz!OGMq`_UjHdQc%E#u66wz@*cOB4Z~n zR4}Z{{U`xDn&88HU@*2Rwvdv%6WU%@j%{e$Sb|F!mcwW#2QZ6ra&9tyo$;PB8nR9|l_o5JJ;%u?Ld0G-daHmYu z8yRQPszEB)j;2kQs8JGlcr^L+nh1A!X;Gl_W4ALGh9-&zATCPl z1OW!f!y@hJ^M7jl7VtQVBjH}l56Q+4Uf~fEM(f2$SfhRDZ6Ra5jEyZDEIV-V8fSKP zc6ZS3%y?#YCD}Lx@*+pTx#SWOAi;2f@H^ZQ2nPv)3x7C%AcPCyagc+9!2Op1e-fTY zLVl3$tLpBVp4pWx47VR>*Zr)ns;;iCuCDfa473cSrEhZeMRBrHJrA)+`-4=(9qw<$ z@~8$?SD>aHPYHx&2E;gETwV=eG_zO0*h1vHxz{L5A0zXDpj71A6K$0;H&*6X^7vg$ zj}DCR%u`J~8?5rlpjSZ!=JC9dDD#}F*!a}9P{Pv(W)Mj=x7I9?ImmA{H?R=Z6myS4A(h+RZs z+ZNufx56`Ihm~F`6k;Oypdm1rLHukF<@(!AOHs#^ycVaP#JG!Rw?(zA%n0fL=xR6=rIb*Vu~Y6W2{_TqXGfIJ3p>9jk)pdb+l=-~QRIC10n88Iwi*p=`DWK!Y`xS3y|uzGxW(*6fS~e)cTXjt zZlEicw-_*2j~4F7#5RW%XTeCpv;n@nQ5L3H?W1@NvM`%e-YN%;g|rtgS7&flS}7$a zayilYjvqFci>?mGyZ9Yvy;q4~p?P1_!-PW$P-rJ?qKAYX^?DD1vgE^cyqHiUPQ}5$U#}qU*Z6N z!hELpRyUgJSa>$GfHeNPgvu{nQ~1)QyCVt9K$$x@qoD=M@LS<*s7~zntK?K zFye;L%i*Mr(`Kp27Xl;DK2b`Bi7DXQ$BVBzb7h{j!0Z|U(j(Dn$4xQ%4ZgZ;g0e4; zM_K@Z7Ll^vS*zQQ%X;wvVZ%BYf!M$ymZmVTJdMyl2$=zKd?7hZ9C6I>n3q%}^5Ir% z=D=iZ+glT-5WbV=G}dlZ)ZRnr4QqfDIsMt};bXQRoqdGK!FBCJVwM@r00$H+eC1+b zF*_Jom=4C4d@8b4a^|A)YOrQCOR@eeeWVgsKkB-gOqBeyAe2FeZl@1hnvtN0dXb6o z2vR$IOw;;@gK5sg>$5F~!N%UpZ=o6Di3WLfY<;#F@IgTgQgb$RS?}#tW}*pW~3*n!~GDs8cxC1x0}>pL)@I z+ZNVfo|$kcgR;6X)%-0UTf(ZGsTfM>#esnOTXVPC&*OK&`A?SZxL6x_RulAd@%KvX zGC){nQCMT%a?RU*x5*~?irE~WTIHoAI2 z20BslBD4`EwJ;I0SJT+n-u5579D{mA6*$OK$bW$sUbpip9VYzgGtgZmyf^<4C;>j1 z4uB7tZ|t}`p@Ur(BiVgnuC7fO`txQ7|FTsZFN9GyKGiG80P-_^=zboC( zF4;<8{ZZ_ajF&*5$Z#s%y*53N;7&_$PGgSa^XDwPe=yzM70NDKLT0CzsVYUy$SStq zcTZcoyFIVO6B(%pkzwx-x_!SB6$Fx@@mW#)8S^YePz)BXN1b4Am#CS`CK z6N;qL13ne<8pYCZD&5nc?(s)efL=MYJz}c`JztP3X3PVXV9E_Vj=cNKvu#nrzw-LP=J2TP=!Btxfm)EJKUh zTDH1edwQVV!x;!A0U_<_9-ps3zRK`cl&l+LvZWzVlz)5L)7@*mM!@AwXrwLO;}fN1 zW`Mb@f@z4rwxtJr1n~eG0j~0i?x?!sm^MxyAkJXAJLUE5sJ2-w2CDW5RZDtNo0KiZ zb|J8ioKsW*ivEuDfY0QtEPRPYp~vp@K)>H3ZF5{VzZXP~NdLO)bb7rC2mg5znb~zc3ot9L7_lFcQtq_xH2izH;QXPc#sn+)7W}Sh1!Uc*YOr99{>0|7L;3f7KK;Vc1Z1T7d2o%9fd<3rO0om zh>R{L+T}!2pkIG_V8Fw54UP|2=pIUU`^2eLA(@cdgdVzwMbQ?XC^eezNk!Q`XK~Bc z#KOVAszz6{gY1O@esr)K!bmdypoe*03 zACw<7Nc%57B05kTtK}2MupJmTPn330b1aA7JL;j333S+I=o6_SlWJJJIKqKp{R1X) z91X&=%`Ofb7{tt@7@f%cP*HGup|lVT68x~v-`?|n-^ab|w2`)@#&mRfI(Ev6Q=6Jk zTiLRz_w>HiXRO(tPVYGXQ+qDl`)RJTGsUT#ail#`^pr$DoKl{W7{aeqf_^3GSBieM z(XV#;)j_{H>6f>P;U{`Zs+*?w&@bA0YJmQ05Wm`JVjE3tV~G@iwqaVtTk}}6?G&&M zTBn27>7aEwXq`@4q>C2mqD8uBk*;A+viuL-Ri|j>hsK`63mj27{MI@Wzxs56SE9Bo zKb8)dIiNnsl5z$F2`kA@7iO3Z^b$OF77$+57u-XEg+uHM(Jg~KACM$LMZJczG&llb zFv_MVLl5r{dxD1{A#ersf&tF<`iI;eD5BSduo?b@QsnWA@i83n;uJfK3++wW_M0cO zO*t39>z$!ZqYzW7NUv(~n~2~nwhHbZ6f2q(RV=;L)rwl)R!Z<_eK2Z=*kJ(gReh~3 z7mJgFreSC*Y}~!xn4Av+6Tta;2ka`NlZHx@J^M%id|)KB>jbU$m=tjPjQQ=&rV<-r z)p$5eHAcd-1{HW2Z-%jK0UO^Y*Yd|C07h%pbjSoiD5fbM`01qKT5+|gYle&361@_W z#Suc4fW7LVHQ575I5C|`LoL{*q3^DG`U&Tuk4gqHLlc!?A>2VCLhdbx+blfp_O-ph zjh8abok@cDeREV&n1e@^-T@Q{mKs%J6b7V%4;~m1cd$!t{s1EfqCfE%?W5vo7 z-JL<71Hdj7jDXusrifY*ueL@bo|=ZVW$PfS!Gr6zNC1q)U_}eyM0cl;^5BH$B9u)T z9VVGs&f*-So?tTaFie*j<{3Zz-7W>ITjfkqS7jxewKWHv`EknWR$#2`(8%Y&_c_r- z0WHw23WGQZ7RAs_ndxdd07z)9M5;P#v%;U)+# zX|h`|7>;lwm>b|yq;J~eY8rY}P&1mRMY3g>Y8?0q9K0&*<+FGaEFWD1;1zSf0E>qq zHbCD+<~_7m_b{Tl1vBfn!NO6nHgFW|nnbj0WVM`bXjw!IYW!?rLvuL{hGLARRz;!= zT9R;Ds`X`98Rn?ZJ-c)S^$NSfZ9;-JwHc?%M&%s zs1%*l95iB>Wmi`1B6lcUjx8cF*&Ee?7(FpR2d>tje2q4H$CWL`EeO#)-p4cAg5204 z?QND6N5)GWIMU^TB^exwb09z{`#_k(rajxGSPuDc$6oIx-dZX?6UpNIZ;FZo1;lvk zT#)Uyi!4OF2RL6h&5GfqXft5nYd%{2C^^mue>TE~zib!#nnWIku_FV+A(+ryZD`G` z7KXLP+{2zi;C%?>qnkSTRFRO90524>cg_W(2=yRL=5{fU>y*oBmPkBbmK>a65v8;+ zye;qZZj%?lp!vfXJ_S|W9CA@1NN6F#L~6jQjCSn@F2vg;ifKkU$0W)(sM|1nU#?(UD7^5Ku+EQJe-H0GT&~j;s z3OIeSm(L*Vj{|b(5i|M7N5M^{3}8O>klY@0t80%GLJ(o(ObkvXax1P}wfKv3SHSSI zc;Rvua9kQTD!OeNCCzXpwWuj}tF+C5crGl6{jgDCUU^&L%0{%6DXlbKxu5G9FeoXr z=9bd1Q8|d|h&DhMDQBBaJw90NaB59`4mYK|A5d8Uz~E-VpTSf!h=!n!;_C*w!yTp| zV2h@~^hjfC=_qcJa06hM@RbFK79W7#{L55H*$A6cF4Y&_`2w zqAYT3HsdMr-O>IWHg~^ zD7L&h+Nx*0*IKHTrZj#rvb^t_Fmw+i_bsl6Z~x` z2aHhVqGm5%$hd8@FC3$r-AlPSY#sm1UV1cN1NOjcY z_(AqGjx)#r%zJSy1i1GDe}Q&WH>;N$8N(F z&7PEolu5cLmDZYeu>ZqnHZ(v4`mf@-YT5-ku2vIOj91NOlFr;C`;yt2P`!8|Y-UuY zDDej&X0)aC(z5*dL2-)&+k%az0T`~IBNKJQ*nnOlxCMhA(^_=_1h}= z1gP*fCzOs-y=w8o>irbw1vcPt3!EA$}2sdx!b<3N61ve_7Wit zWEUazuZ=}Wo{+|6;cB^Bi5el&@@2ud;eiP`;TbAc!NZFIAfOPHFI=Lmk|=nR;}oPZ zZIVW^p!Q|>x1^Ne0Vr2j(ftb=7&NU(ThA9g_1_%-#uuGVA^mSUobO$x4~%zoa71cFCjRQqNp5WurL%pSh5@JuJ5 z!Oti)OxtG+e95S$2%(#86d{3&*pxgtnZ;RvVulO6(b082V}Uxw6v;rkXMSBS>BxZ+ zcs>?2q^hMj@Ia;FNDf9-VzMgG02^i1Ni`!Aguke@XQAs0yi+9P@@rrm(pr{3N~W6o z7nV31d$eHMpbb*Ji-slwm{I=|UcHYYs3EOTJV)mWH^xY1Zxu_5oiD>iu*qp|ku3V8 z8X%R<86zu|9nJQ)H^6;m+whn=cs9iKS*TN`!*cj$3n31Ny1nDi8nLt~55PK8|CQG&1M`difiX+}raA@+IPMT!HzIYb1DGwPHr5XxG1 zwy0RE8+pw>8#aR@Lmj}`s%cczaU2<*3aKKl#uaxb8_kRl7gyau6*&Md) z!0Qz77(=F%?V#4zP)D#_r!(9cN#Nz}5@i>_AINQyZ-9>&-*_TRY8ulfWqi!}(=qxi zh6$VBoXP%4U(*PM!=3@vU?qbELs%!8Mus|8p>|g_0uP30GvJ>`GE^#xUIa4$?(zWU zFxwuQI20l5=!2b^aE!=Q?1BCr@b3s){{l=T#It0FAkwKAW;5LEsZ6Ul^c<%G(LW=p z4Q3q31Nb}0jVa)UR;$d}ftu{R&4Xu}1^w044A<#H)`MCt(hLkn4Ry6Gr&NAc$$u%# zd2D%Mhte<(uq6uc`22`Xio(?oo=Wu)EnCG{$W(k9!+A@zg>EBwTEb8BS#4%^j5g1L z;Q~=w!?dSI*rH*5hIzs);1oe{5fPD|45O^FO@cX1pBq#;&@k@ji1MV$MtFd(-S{{b5=Rx1y znrGJ4!O#Lt1qMZP1fl9rq5okm0go7PfAfBI1q6{IBLpsT2H&RCwi%)dgQTR3qerq2 zrX*m5O4lsrX0Y&cdE|w-@C>kY3N!cRu#Vxp4<*Ahs(T({gQnr?Mp+YP3=eSb3y#?< zAVLS8OKL2@O~OKt5-BL8l7Qo2QmR={KC7sAFbbj*XHcxnLZ*4AbmD zCw!Rkj*;{I0Lu=L{EqO=u#k=;E=K`f-~%d@h)VC-So@Hh>N$6v(zAAB;;f#oGdB*EavM`_VPcEcGnQx@u}1s*=7LGZb`;c9z;cmD zCX;o9G|oe#MTC$fz?C=-U|9f=+l~V8MF8|jgj~1fnppI;t*aVaUFBo<{OXAtCO#%F zQOE!JbAR*f$^UrSN%I=_ef7KNfA-H;-22l1N?(80InN*U=@p9yzW&zIryKX=4}78J zlPkWxwfELbuFTDk{N~Qrk9;Y9(Kr8g+r}Gr-g?&f3s&-h`m0}k?18_#;EO+e{*Lai zK5^dN_2>QMo8SAJ`|d93&!5)yo&Q=ReWv-^b&ouL<>g2J?DFxJ&;RL;eS7P=pZ>2e zAJZ27w+C8A=1)n+hFk4F9B4oOoLf?zO}BhA+uYf{^84Ep1^uVbUGeaP8#ldp>}9!c zDI4cp`1<~VhD-O66_dv{(p(x^XjT$<Z+X7yr{o{`U7b?n|Dx_l9fch=f^22~+10W{yah^F}9z%DZ}WEw@WuJJ`OlIC<`t z$xU0gol~l0R&L8wlIQMDZaDiK%UXX<4Z@@n?Le6NjG~T}EzS0613Xhjn>i8k`g;eA zuidrs{`b~j5qt7$^}qXKbnoULA3gk+>rS;^{?X@mJbG>P$W!lWdCrTE-!S(ZmHqFPUU+EvW5<&hVt@U*dGU+iy0QEAq2!*6e*Nz2H?BGPM{nP; zf7_?petr4>zTiK9cHlQ=|6g|e@wsI;X7B!o;cx!=ku^tNz5A8te;1F<|Me}$@4oH2 z+ZJzndCNDx`c7x+#JWuC!pgnZz4-T^Zk&Jj9lP`Ay|L)D+j{@?_VRuI*uVXvpI-jh zm#(_w?OV5&d*A%c-H$!h`tZlzOg>tFNzbBruidq;c-p_ctnaGpz5dG^p17bC2?l^H+lFV30c7yt3n=k6^RE*ZK#Ydr8=UF6+Qzq{`01$u86w#`H7?6yZMBN9zN%`lW)H4OASALXWwrp&wOC+5g!8$vJ!8D?Bv!2YWx8-G2X@z0$scy$?Q9xj(YS{?S#x-1_S7D|TF~ zKKbLfpZYC%z7aS$%;4b-2HdQ-tw7qrDv|MB{b%GyjdsmW@oWq?HnD=b?oY%$gMnc8@D5Y5(#UzR+^~`LF*#S^b|6{_1;g{GUBnUHrqg=ictR^Ykz4 zOI|!GK62u`xlf<)%drzLdi*nw{^?K8?rRv>{o7-{Kk(f@eC^NYKe^@B%RYO0S90pg zMTO6|Uj6!ArK<+(e)Ze$e`Wj^uRUWdy#21krDV~~=RSDvfqB;N?^xgV`1w~{{R{cu zpR8N*#argq-}qSSdw;b4|4nC)Yw4czo~>MU|3Kw@S+0BJ?cU#g=b5IvR@^`Nths#K z_E zH)r4b$wTM-=Z8vcC7OLLZ8dxmMiK?22ad)wi*rEO(=#u^-k00@q2Yf8z3^SGL= zg5k<5;$c8nWp+@`F#t<>*~wHP4c2H_pyP_7KpFTXh3_O8NzEhVQo2%upq&eAZXKLe z%qJwdY?<7-Xx@99_Q#KU@$38aMXz`bsyPq+P_0s8t)i|lUQ`uD5sCm+$8}pPLM)1+ zp7(SOF~c!T(^EO1qw%7uj|;5;oyW(=^ke3PQ zGE-zBnTq^BLK@cm9#H#7Lh6?-A>=i{6zVo_5Yn*hAwud8%q8UKgw#JfkC0zL_9O7; zUkIt6o}MO;64G$`uOQ`dLK^CxfIm;dKmQf}EF)8mM*w6polZ$m2g$31G?G^cGGO5I zOG1+Kr!Ki+;)>55O$cGvxa@e&w8s?)_vir6!pH_#y{YNx=_A?iQA{66)e&-2ge)W@ zDQSADJ`#yU<`A+Uc?d>Lhc}N*0sPYd;et%jv04=ufjg3nq#|Uh9$KEqlssZ+ZrsrH ze4&%W3tSJW&baQX1-YcC0ZIv3m7-#Jc}rNeQrXefILss7APg94(VShTBj;_i>@nU) zssvLR9#3nSShej z^Ts|}U5+;<76Y>T$iY5KiYkN6JIk92VhGEahL$o7jh8sFx)sYdT{GAYOfB_kXp0Y%CF4ZkRX9uXJl$hsu`w&B z@(Li4aqwnVEA3Ru6Fg%f?)RL~+6i)3DZA#*oUQHROAH8a_`r8PPID5elEu}coh=Y3 zsTBqGVfZAz@MdrG)CgEyQp)Wkp=Lr*roYkRVeC4 zd7>T)f#m`EXpCk}bxgBcbu&I`mThw^?wYnuSLs!#Sh`0N(s)AI$s|Fip+j`yt|N~q zuC1SUJRyy-tlFN;wRd&MTDOvr+mjtxIg?7H7~nf11$6nbHK4>QQWlL zxa-7=W*&T67Hu8fxpDKEJJ0Ulx(;9jtRYlqu&Q&QY8_Nv!mCo{4r(8 ztFK|z>!A8vbgALh0mX1C#=GCTdCQiaL+iH$x^H9k=W;qj6LY&0Jqf6`VC(44vo~+q z8mJOv!xBV|_7Jy0KpaOFAZ{Z|7d5Dt2q7B+h$@5eZF+G=Nr?1zIVZc^p>J%wzqH0wz&egC;_>fL4wUv_ffw4XHV72q;^n)&+4! zEAfS5h~Wmlhsa2(EkYux2x%lq_>+J?@d#ju|L>r4k6QVkcPL}_-5WZ7m# z&uWeo>ZuuU`5`scKuF{K#6%*INP#?>pO{EyJ2N1x=1Hm6L}DI@t@iE&$f>0h1yz>| zYPL1e3Truttz&9|J_j;3f{c?oT02|YBwjHBttI8ex|(QA)kfo-YBZ)kAR4hJipCG8 zDIbk(RcLHuXq?-TNPL)hOv#C8O*{fSraX3p^{TE4g{zZtvKA)}+U4DvEv;2l&7F}0 zQ;50`*aSmaM@LsDLs_D$JIOgO8Q{EQ+6Oz@l8HpJGm&UdCXse0EmlOje3`7rMk_B}imSdNFl@273TC&xm;l|D1&jq#*c1Ijk9NoyrwTk6wY|u1l&_>p>&522GCkuM4P^Fy7TY+w1XMq}( zWuZprxVB=+;5EU41BJ~{T&v`b8`R0Xtyu8lLfnC)wm8HB&FSfBt`opFEZ~dDRAerml}yz`euR*Q%|Nlmv8KU|>xVaO z-8s@f*o^B8$hU$?qk5g_kFllOf-khb$uFx{)y_0U`hulw;7O=aK2i0y15{giMh|WV(K8x`BL@OgBW9k?Dpx^T~9>+@r}f>|ohv RdV1l= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302143118-Binary.backup b/MikroMaster/20260302/20260302143118-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..3704250c2de3e04c4d119750c701c4650e037f3c GIT binary patch literal 289184 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302144005-Binary.backup b/MikroMaster/20260302/20260302144005-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d55b1dc0dad121a91572838f0caf5b5dca1b4a99 GIT binary patch literal 289184 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 z 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302150004-Binary.backup b/MikroMaster/20260302/20260302150004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a5a5f4cef6f21925d876c59c193af586f5181d1e GIT binary patch literal 289184 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 RdV1l= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302152005-Binary.backup b/MikroMaster/20260302/20260302152005-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..639b59b03b37d991a31397f87d14c3406c634e4e GIT binary patch literal 289184 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ⅆ-WzPbS9rBzydTr_#V%C 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 P@Z%rPEF{zH*y+CkQ-%G2 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302152005-Config.rsc b/MikroMaster/20260302/20260302152005-Config.rsc new file mode 100644 index 0000000..0275e8c --- /dev/null +++ b/MikroMaster/20260302/20260302152005-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 15:20:05 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302154004-Binary.backup b/MikroMaster/20260302/20260302154004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..f6621fc3ae7d4981374ae6c3328d70da8b841ee7 GIT binary patch literal 289184 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

  • K@wKIwY}1^T@L%-ob=M64fR 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 Qdf~@Eo>@qy*|F1q10-Vm^Z)<= literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302154004-Config.rsc b/MikroMaster/20260302/20260302154004-Config.rsc new file mode 100644 index 0000000..7b9fbd3 --- /dev/null +++ b/MikroMaster/20260302/20260302154004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 15:40:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302160004-Binary.backup b/MikroMaster/20260302/20260302160004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..da2c0e254e4ebcf60c9f268b8f3a1b1706373f99 GIT binary patch literal 289184 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 PFZ}q&GYiQyJ9heS7{C2y literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302160004-Config.rsc b/MikroMaster/20260302/20260302160004-Config.rsc new file mode 100644 index 0000000..e837522 --- /dev/null +++ b/MikroMaster/20260302/20260302160004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 16:00:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302162004-Binary.backup b/MikroMaster/20260302/20260302162004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..824e609db01b09eabe74b576bfbf73ad91b6687b GIT binary patch literal 289184 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302170004-Binary.backup b/MikroMaster/20260302/20260302170004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..573ece3ac1becd56ec8ed53aa1d98969c832efc0 GIT binary patch literal 289184 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�i!xT9-yXQn>>p0~z|ebZTc@nQ(BiD4^jg=&m zf6!zj>d*ygrxg$1xU68fLyLfyE_-uJmy9`|oYrl9TaVKNjAoq=^Ba7t-y2ru$g4Z+ zw-0O@-^JvJ`O4+AhBH`xi#P1*<&d#XCcK*WxbYEZxt~L!X}g%7lkYhDmo`rprnqw3 zHh-tauK3E!=nVz0792+-N8HYin-OwtVU*tz$Bc`~rUl0Zj~ay~2bRW8xS0OQr&aYk zH!gcjT;~VhzV7;Z?~=CsHlf4!3FXvgbyuH5vrCUz&6ULDXyAf|f(+ll-kEyrM z#pm4qIC0?SjSxPq2M$7AEQ3<1cMyh0p7J}^TN3(}{rFqP{jVH^28OUI&FmZ1`Ag5> zg|pGhG*+>{W}M=_bHdaE^VU5verG&9Vcdh+vb+1d?IZ6MPCtKpoP7&g;w4HW;}5)Z zYnp52=Z!surN=j|D4g}thG^2Q`Henzxc!R))7T>k({5eb)qS)j?Jzy7MbCs3?)~f= z{a#3|N~OE!7JcefwXfSu+Wn*Bi>^hr9y$XD7nEEL3-t)F2rDvY6*?(;EsJ-ue$9M-{jw#Qp zyD=eb*#rTQ-|li zUXg=YO(p(Mhv+B2 z9~~TZVs}oPmM=_OkB~h+t=^H)JGNN8pl8L}R;z6W$hJ98d8Yml-9M5!0heex_>S*3 zb@PJ;N7xGvMOd1i>+1QsYWjo7%R|Hsf*u=%^qbKw``D;J+p=XB=*5kBW;X9ZoG@i@o% zfc#{yn={*b{UdL~*4%D2sc^LP=yU1KQQDHR&teLP+h%V3n7Ym>FYQ2|279)Pl8nmw zvjq+9OcGeL+N~9J-u5$3;jhU26`5KweZz|{|F4UTE^+&>?fcjE{cHRFwSE7$+rDI4 zhd?4yU_1d^E*0>ld_K;T$}zTtE9DXx2bU6ZLMY`EJT5^9Wdu*ck;~;Gwgi_;FgB0F z;mWvVY~y=27r9pPJzI;6cL)fcLZ;yIWm2AqkMr0N@A$?Zo}*97{zIu7{^SQTY7(@+ zpSm$nI)F^nw!k&D7bYG;WW=Y=zf92fG-OBU7Bcfd9!(ZHpa$$ym5E@ zI~g6v=~xE+FqT1Er_bmxd%erJWe@7B!COOGxgLL}_-gk3kEc`k>)uGmF^)cUTbI#+ zao8e5?so6rN-E)CxGr;~g@HDPRbGF#Q+Ss!r_eBOCmn&DfI?0_-uN&5qT_EZrCpcp zkf|O|4((AK*L28Ws~+Q?zpA`=?`HO{oPrkvyz3>DSfTe#S(|za`wUy(ZQ7umIs?6@ z_u(~oKji(6;@xgoRgb3!UJjdi%jUIB(6Qx~FKizaxIDvM>PnQ8n`}?HGPBXGVTyvp zjyamctE!*&V~y+Wb92>tvBk?yA1}oS_R6l6`duvXts3U~Y4ZJUCXU?}M?Mbl3r}m6 zRs702cV;~=+Wm#1Yf3Zr-nF(pyG-}*Fm%!3++lam2ZgWgFgt%QeP43!#ZI?R*1geU z#O!B238&g6#hmF9P~g^opLxb7zx;yOX~(6Z9TKO$oAbVZ|Mlx6cN#U?md2cQzs>uR zY5vNEI=?7`l7VGVhW{dITbnteNO7o4P6fR)TKw{>b=FAjGR1rpQ-NrIM;$EbVg`rh+zZ#(_6?4Cu{^>+uhS*p{S^vF{)=XugVaxPX$rUJ=*ap-{n$I}<--t!^Y$b!xoJ1=NH%aVAE0Q=Z8<2 zuy}6hy@Oeg1VdYVc-B2asJ6U}tWR~(l&lo+@|&kCbCY(K+7Fq0{^+TvQM6C=2xr^E z>Id!0u4TM__^S6*S97-(IgPsL4-P3QSn)BRtd={~O+%7hr3rw}P*e4awCkcoIwj!Yty$pk{a zKq`{(gaRp#Ef9zV91%|-!UbGDM-E3V9e?#^%Um3XD&_4EZlCuODRqNsRw!Qnf$lhsi=UN!3L`@4JCz-k$dX zQigP&ihK%Y`5l+nMQOLPl$U!r3iqmuPdbssBjXfQq9b#}QsSP<_1oUhWVeW+Ll zwH=m0Db^d|M%{bte9?aikGFq`#f1W2HO4Y#v>4s#WE(n-_Mf-FIk2{Xb1=v^VnbTB zA^C`>|M}kmLK0?aY(nBpr5GEvOs69kniSEmFTb*5+*Z>MrfJS+pY7hQdCBSLu#@|s z^x)i`r*qysJAT@9yQEJyzv1)U7d)9HGqZbSlJNS}D3A6dbMLqFj%&U8+!CAK{FHe# zpC^{qvFg$_S<4s3Z1Oo7b8^cbGfW?KD$&g&Eom- zLT2{$*n;;lX?avkr0BCxK5^^(kZbuD0v0_!bnQ$)njK~9;nCT_6S7+7&sj09_zc?h zF1&osojyZ1G_?cU2Uyl%`v4moY@fdjrmpe+$XBTSIe!`K-!j3*X)527oSHNh zCydAA@%U1ig3W{5@;E#hN5aJva-KxW!tdloK$o*O9XBezTr(zk@YD4J9CEUJY+^6@7a`~;jgFEf4 zt;ha5R6cx(@IM;&;gE43UmqWc`*4KZ&vBn0%r+@2aue5N^^+}G-EZ_|%Ych(r}mcl zxMsfUL|`X6b90u}X?tZT<5EwfW}W7n7ChW{ZpQq_zGugeJ4p$&^SP-x6{qRMy@vdl zn|g#Fi5z^$+T?Vsy#YMK8< zB;|Xu^uIrn0^g_luSQaI-?;iOMp9~7SGxHcYv@wmtNo}WtH#W%RIlgxowiRJEVa=L zn^QE!C;#Q7uD%-)$$uXcDxKUu0=8N>F7xAAF^ zWnwbtz~090PfvavlCmIR`e9;~e9dFl-IT1K#VY=a=3mh?geYm$|A8Rq|J$PZ+0x;Q zM1-8rlgi~BIgb#CFoA$C$N4-$B9L&{JgGoJNEBRL#ODe`Y+NE@D->*@REqJ1m|Vb? zN=WDWd+M8XuD_?Y_0Bb$&Ew)iT+Wv(9A1PS#sF6?b^&zd!?($gbd3(jy)#CHBmuzlaF*gPcm^z@kt8;+;+o;I} z664(L7uzc~R!n8bYTZAo2e78e)6P9@hGxt=p_zKlwzIL>gpf1Yj?CS53-3A~{WS89<<5~y zSqGw;z0ug%wDC*YKgMRPGdF0hg|FGNfQ8$4U5Gl#IHYyvcE8Pm{;-m&S@39OIq5Mt&7wow_sa~(xW*BcBAT`;M)PgeSp`AsgUR$n(iC>ZvbHnqW>(OV? z6-E38p5P99^UtCbf93Vtmy!R<>tA{OpOn|nrjSg^k;$Y|0UzVw1dqUQj!+?#%Q+$m zo1+lP39dk)ka2hfmm|Y*E>}iK*aA71FX2g~xJ=5^eR%PEYO+?)hr^L5aDp!p;J8F2 z!K6~Qkk6IkxEwz0Nbr9AUa>zEzy1C9iW?j0f1?V~&|Z?hDJB4p`xqWGsMAvnC(o)Z3Q~weTf+W?G`fk^DIkgeWS{c0#)(kAVa9BRkYE#gb zb{?IgQ^)gmK56@*J{hh5@>N~qZ{Ou5%PNr3`o)KvL`+)P6Ywd@Sf=nEO=sDckE^TEcf<{ zH%;olWh)h{-~aBSp_yg7uf5yPTeLK2L;pt^Pl{h>%-%=6+kMLI92~>=GKqxCk>G4x z!e+~bgh+s43a&ybk|~5dwgO{I1ej1F;mLV?KA&_hzsJ&_HL8S*vH4O7n^5p&0vQ{V zb1|-f;1PVDgfHR<6r2t+csW0>&UtppjHbRJL0<{J;nrL^0N}ViG%a!ppg(#mu zi8F-A;}d!i+Z3TJ-Fx1K8isUzH7_WjNn^rlDwIv8LS;TGl=7mn5W))KHYV^0wMGKP z4=GS1kU~MHTb-#W@2Kc@XT-w?t*{E@Jc_lW;z;A9X_4i**%*pI^@xi86E!ErN zgp1N+x2}2ee8ID#drJmHcilE}jD|7B@|gLJ!qx*@^y7Qn8eEsQ=zg<0M)9Y;FV%~_ z=#ZN2I5VfD>7kB2VsD?Hc`j~ei*ecfhJ&^H0~*IPyzjz!{O!a?`O_Zu>c*SsRO`Gqx9A?c;Om zW&e|$W}6E}-0VN`$ov)Y^R!Ptw2B#gFnU+w)0rv0ld)99Z`O54tFVnjSCpGvV7l|t z#vBvId0i~^-84W|8qt3Et+`MIO>l50B;Vd2R&L(A)(6^!e7zqmT$vV(C(;LhpPV^IO@ z)+aq)$`zq)`r6J-Ds8J-;ZttfJv;3J7QcD=4z~}Rw@qt>ubR|m-H6B2XN}*O)KOz+ z&oYfGchaTHS8Zps_&* zON#1lh?rm(bYXd`xC?<4oBEkjZ{DXmJC9v&x9)k!IQ!AFR@UnlEZ@ZbG%4$2*$cmy z`!DoASgGDYnQmFMC-!F89cA1!n+Gp9-P-p4!-wW%Igj_$TXFSvhh)U4-}n?B>gl<^ z`=eb`6?xpP@=?R;`>WH(cqwF3)5@m0 z>m6`4K;v_L9JeAtJ;Qa&I5+pDG3|Oh*b$=WHP9o)WB-r>Uw=8G#EI@or2HPyV>P5mj^$G5--wQjM>Zf(8izE?*3o{=@DF7AKU;U5D9 zrz^J|J;S<`x!3ykbn4q1u50&Zo*sVSu~{F0p#}RytF>dAzUvr0xqNu%sEk!t(~`3) z{a^Mx-Kftl=R+HEV{b!n27eUCXj>yXivBYnIM49971{Tt;UPZ74rUAchTp(Mi9 zowhaC_8oiJ$BKS~y?1X-mtHhoSLjbvyWvCA*+dlY6hYqfc=y7KVAS@Yi)^nAUp$-dXc_v&Tm9GT2KJj-VF+wQA} z)3rsR*G4BdOXzjUw^`-ApPAA*LS#A!nngL_z~4d7VxAXyXzTntn8>1WeXc zC2Js4p%!V+uAzbcp?yb-D*lUXbfLdi-s z5ld(^32K!>8A}-8eWmXTM<^O?OTt@SU0n@|7bpx>f6Y-9rLnF!EEHJPz0c2pg2<#k z2b`Etjg^VW;;K;go-BwA<%gl3CJkyhk|kxS_WG|DHh^mkg^_Dj`=z?UKcMy~%@qpe zy1>pEc2MG%K@ufg8B-U|)PbEj?0|UiVM1pFm6TZ`jLXBx#bWxGKY@}aazY_VjMb7g zU7;eTCO$5qrU3AIJwf2O9tE-O5z42MHIT`A&QJ^)8mZPKp{Qsl%Ym$c$wEPFODK2j z=*R-nHPE%Yk+qCrmeZ9l{#-Dc^;O+mK+j2tVHigulwn->NH35n8Jr3{LL0y^$8Ra{(Ryi%(qNG^dbR*xARV^I*h z0SUJi3SvWKe~nr*N}x{NywA62{J{E zb&{gT9F8eEeDf&C1{uC~QTrQGCS z|33f#9{>;9eDA(cs#U61%A<$`m0DX<3VEp>G$2gAz72#iv_ZWX+91;Us<3Do6``fN z3d}GZ6c~6YD+|?Rp`f|FPI@VZn%xZ$0%;=&+Ysr#&f$a*#hENGT?GZe!9-&+NGUee zk0{f?xroVvV#!eMTVFBR2#Rq#!Z{Z>=c@Y$VzPh?BS3!XLjS z1G0!W%n`7GP~F!{092PZ2rW1r-ui25OTc&|xDOOAuFirY_tjZ+QgV#-1(ior5K`8t zW(qP6#F!1k({kPDQ90LP$Y{ zQq$Fps%jHtiK>~D-c-b7L{JeE^`|1HHj;`MBdG{UsEA3E!v6>=Vp5~vf@msYjDRZ0 zAVDB9WZmyRmr_oWY7eTIvm70}4TKI#Dq=dabh^37RIj7u`YQ)FG)ej-Dncn#oyv05)rzLn8Uj*{8HNEo%c&{t&lqT?r_?(GrM@NwNu(h#22bejaDIRPm6<#0_+X@71opq@-c&Xy$Vyr`xcCx5W#G+)su zlZu>8^w)eQ)i3CL9|f_2WvQfnVPImgHK3i7kdOdW1I2Fq9V!761NDH3fnooTC`A&9 zq|axn)G#bi;7{NQvoZ+l_wi&f=yVW9ut@+Hm;}GW|D?ox76A}R(k!5U#oKnM8aMWu zStouu-n(JDefE(F6NB1vIO@yO;j`8$>w5m;M(Ju2Z#LQVc#l} zf6Kr65n+Z^#qngr|nkLfQEm+ZTcdu)(pp z4rFACsz`~rt^9Bb>}nHrVtl+ZJ_?L$I@|?tNQ_s?Vm;$j@+3T?vYTgYOSL_9cozvZ#Pqz7*yddeh`N{uFwsPRt>1|S@P_z*jz z0N&)~S|TnXR-&zO@4kCA*ox%U8X1ug`57?SzS{x(06jE@asBRfzyq;tZNgVPkVW2^ zd=U?2p&<4(JrA5i2wgx3Mw{e?l|~31gHhJ;1nI&8TTo8|T&ECXIs#)*&caXN33M5D zC9u1$lmd=3xevPD2(wJH&q#8aV+)#^C*cbsXUfT5>a z&lSJZul5rYVwD>0Z@ce6>v%%zDUr+78iN<*r6(#l2!=M8OkOC64QvRyp5^FRP5LKb z)H4jO6sabux_?7=(&ZyW{6(h&MYL#T>|P&J@T z*ZC_{Izlu$LUcMpMs%G3KBFPv*#D2cFM)5PI{u%Pd}tjz_YEX+3?zZru^roSLO60e zA$Agy5RUc-vb45EWJySJoKR@OeU(Be6ha9F3Jv$!(n1d?H}u~Er5wE|y=co3QVN9@ zu>YU$+qbLt)~nS@u@eZ4OY&XTe^=B>0zn5Pyyv_)tzS5MgXlULsOnCQ@D@!Z3s3gnmne(S|U9Jx@fh5n-%> z?Mzz~QeG#bKM}#IW)tp1i0H3GbhSdXRUx`YA^Mg=bgjY$Iw(H+wnA`5(DTJaH!4Ig z7889(A-YK+x>IZ+Z3WZ6rwv7qPrBLyA`5)6ry_-qWct5 z?pKJurx4w)5Ivv}{ZJu#P$7CqA^MR*^kaqS2MW=ziisXph#pahex?vTst`S)kn)&9 z^g=PwuZs!#nXn}DltT2hLiCQ8Xor{RT`$pQB6`nDw7h_PLy0`KV5Awi)ZtQ(O9SL^ zCXrg$2xt~AhY|UPP9{2>NZoV<-Z~Ozn5F7(Z>oWeF}zaXFgE_q{?)D|^)9WlYeCTJU5!E-P?Z$#1X5A8T+q4y#lJL|?`q zCljf?VL;C)q|&nrslBJ-&jc>rxNJZfHUc^gm#^S*Ixc7ELrd>Jyrj}5-1#S$DAOG=@E$6|(TG#fEQb=Qp=AZ6;si+M z>21azEd}HoM&y|a4R}70nQ?hV0hPmBR0Bg=pUjq1Gv4|tE~b|iIa|wVGW>YSL@*j) zuF~P1f#j)OS|SkA{0nps>Xlp;J?LWgA2ON#D+k%6XSu7{g={jT;bkH?t=!0_vPB^h zWD~yGykt|5OT|VWl`Qf|_ba4`@(9`cp+bsPCLxa)2dpw_$m0`=ERz@?FivopR79C% z>`|+0`)|(Bzn{)cEPW@hCMKEZcquKJ9$U#&y#pkcs#PZQkVIeeaXzmhjO-74d4zdl zl}F}(W{%NendEUalSiv4su&hk%sgBO|Cm48v7 zGaT8-WHppbMFXi#UQB7B4%2GVDw0_gFn=-o;I?$#5%f&W@{!?I=Lhr#g{W;fvus`i=Q`ma2 zTdlUKp#OHo9#sr`lTjc4b5t@z*`Rj<7VleP$A*&OXh5_{ZOu{H5-nQ07_(4l zKF`|4f?2xFRCTi586>)laJ`;gH?!;2?0O5k-UDYOY;9dd3hGe7yit_P0klgoXJqq5 zE|*Gw$t9mNDml&f z0EuIc^Fvsg^>5+gZl;KNVMak@c4$VuHzqwVWP)f6gT}m2Fcu+G2QONF%>0FZ7?Z1) z`pa@{AKeVjQ1Eu5kgr(cB=B4{g|s`A;8On36gW{R$~r1Klb)qgrx@Ls85C8kAkd)cyR{|kt_7aE{tk0zcsw-flt{5oU6AeT`e3%`{EJ}Ii$Gn|>i-7tU z#S;GcS|ZgNOZl5tuU;Vt^kQ#wt*G~q_zwSdy=T8lxKH-nuR>(fe!|Lwsr8tztsiH3 zaIM%&8#Li=khXkQ9PG55x)L(BvVUaEFd~_rW3CoK95B7}M&q5C)R`!QqG%p#8j-sB zD66o~zYz%sBNp3t(V^K#joB^c!ML<8=Glpn;mEWsZaj8`8VcWx=zZv*3PWS0gx*AO%T=qX%eL?SE;gY&4SxXjI>Dvx;wCSh=?A- z9uU51><$iNtJ3Wp#sdCb97degy&OiI6}E=pgE%YWw}{TVpWg?`yE%+tw%a(2Ai`TY zj9@k6K6a1Y!|x+>(7=i9CJ*rY!v*{!5E`!+f$c~$%839;<9$T2-N%26O=iYB*sk(p zejh6#k8*f|@DAd@jo(fpqDS~U6-4w5hp}1h*Bm}rz=LQalpCK3%h1l5qlq#^5lJ3l zcy19z1kWwXg{UB`svxuxt0)L>w2M?g1QDW#E>qI8Vyw(y)#WNBy()u9Aw&n+4OT{E zkY)C3+TK`Y!9a(oAPhi=K0qW7A`k?d+w|}v8pwz^fCm>IU97agYukTnT(ytrQ4h*v z(2;_8js?fB#l;f5;~cHS1`QUGvkN0f3A1(B2<>iNkqsRfPev_B#Nz&@SXA2>hdCPv zuG11pgaHh(+=N;$i6=B3dwPe*SmsaLyM~>+n>g28zsSJ3N+!;A%dy~AAN81VY}htr z$GMP%-Nd~G_A0ZmpSkz{z{e-yl3wt0!N-|c*o^ATyl7CAW?{_63S;Z45?$a>9kOuW ziQ;k|V`gDC$HL4+bMp2*Kg#CKtGSM{;8|lG&5l=h6Q35^^J#HE^XVSoPLZ*!0ga3k z!M#W5denhj)2I2ZAx6>W+hb!|H$;1x5DkTF}qzy2ppr zqV?+xhUB0PH=1!0SqIj8KgUMEt_-Z141wJ=xE9-Ut8Z`OR%rO*)!pG#O0$}t7*35x z7;M#4cet}1e4UkHzq^lNrCk`iiD7;A46A;D7*@AxH@M=`&-2{sb3Cl7_FP)>MdQ*z zDSg;=#jE%48&UVfh+1OLtAqABUOhh6wYsZSvzV#O1mKTg0u0(1>q>RCYOYxJ?tLt~ zCs=lnJHI`fx~#xiSIvxvusIzYewM*I{2YejU`FOa)TmpetT|VBgrfC&t!c_Pjd$ zi^i*?^s%)osU?E3XiAH^n`G^Cxb6|I9d6IHBfe-{J3QJE2zJJ2^RF*Z=!_ZRl_?NmH%26mv=@v~ zdy`<;aA8qrda(g~$p3Z$AkIqwKkL>|V~TCE;Ks))g|%VsNZ* z&o$THXPV6VCM;~vGIH7MW#NgRC9WN7&$Z+BCaz_pV_P7owZ>xWoPun@yS}#8V5lmp z>3g8C8f^a5GFHPX5R%-j!xf*=&QM$<9=~sxuIdR0(r5jLvE;y$x)#5HGUnRbp15dT)#@^8Ke47f|&u?JW2|G!W;+#bdM$sYD=I z)vl%Dfp#q!*R=FH1(-S03l^S+`$0E;_wn>@9-I%h=joy^EKd)Pgri*>szP1sv??v6 zd)C0pmirbC9>xxa?P2GRA`(JD7Bn2ZskNpmb2}syIYsfyWOq0f?5GR`Bb8b-l?ZFD z5B)@@HHIPF8INeEc4=Mie`_R_3u)_d&?u6vA%9&RPke^6;S9Kgi0b$mwk-AB1w>{1 zI5CBKSl&B!nC;rREoi~wkk%HAMcbTy1N`ha%jDl6Q5`$SG#*9XIpn!JffotiCs1>3 z8TH^4S=RD6y&9*NBB`B<40brpxkpuSIv&m-Rgnd+2B-Cv;}ptrB(p2`g`+7g5!F&C z016xEilmUi4ur$;R0HqGkv!4frTmylOoP#k-SkC+ti&m)K~m6GVnIdH5;rC5&Gl#=6RIbt(o zay%r_LxMac(G!l?Wa;DoOhkX-#~2x@%l6*5t~R7hy;6&^CWvn7HF96NCNl=(i88oQ#5z! z08NZ!p7b%9yLv)qI?dj35J5|>J&Vbn#49OWx^P*Ki{;!*>9kCijPFb$Uy(v|7T!La zNIfc3S~GS=rgJ9vLd#hwMlMg5tB=|1wZyVfN}oELds)t4=#%seqh%!@Eob`!!JrmT z`L$#!&>9IRJG9WWgocy4L({sVsRYvgg`kcK!_jzGiWzXNfzV0e`1*$1&FDRxRPW9C zqFIhX5g`9)tmbeK19(IsC*u`si(tEmesM#p9W+5an3`f@o zBH_>-{Z>?rPbe;mdIc{kJ6fF`i8|XXYC-m*jy8+RJ7LNE<`wH3cJy0W^&H99oJG`g z7CY@G>)}(#6Kt&^4jD#=uv!-2q^)6QEeo^Pa)Py%YZk2VgRxk`NUdBktn*!EBE7bg zJjDLHIcm$O?Trd4(0gLPqShGWN?3)>`WKp2FUnr^YHQUOG|gYJzM*n{B&9Lzp_ICy{{1af5k9j|8r?5YXh0hQY5oQarU+uVQrfw zM=!jq->PcmVY8scDCi8c6MfkWI@Vgya6G96{d1e{9{AGwP}*9vv}*R!jU8tDlEy-TqK8h$1iTG0;ft0^9kP3EaN#5M?SR@?W_-wz`;aA1! zIy^LpYaA$>5>|TSL^3FyLD_3jW41a|I@)?Iu`$&Vj<)-?NK*4hV<~?y)``E{60uJI zvbil!_ghWS6IR`6nkuN#AhSP8Gu5QHEtcpGBtp5H26qlKnsac6KHuVF^GC82gl&vuRENJc5b`GzK|f3_u+3Xor>@bw} zVzacv-ITVEHPEzV#XJ2bt*{IS$nY7C%BJn%5qVX1$9@*e?3WQJYTEP}>87X| zjh}l5zPuw*-n8*E%1wDQn?FzXTY&}hCv5N zZ||)f{-n3J_ZAL++S}V}_#)wRG;l_Xh_-U)?-qsB!pjx%y;(@45&5p3P4t06D*Z4>G0@tE1q+uavX5k$lX z(L@;w2cRK`$AhOp0BL>f$h# z0XK12T;e;>54xFSmxU!hb~?1p5}$%|x^O;MzDs<+<4b&4>Jygu*eNa6B|as@Y0~!DPXbAeI2JEQuvREc@ZCEiC!LA^k5enI}5d z5<3YG?r|I=*;~i|#<9`(JHKP2`||{&7A#jR$3+V0Ta7zwaIq{F+8w`<>!F%#iEyWv ze2^ckUFqwD=DdK;!@UcL)J+H!aB=d{fqj<baUhvT=PCAN0)#k)^2isDH7#4)R4RE!gF zq5b+>D`q%=DxdSx_D)$e#zJ;XVBU(+I5r3ZY`_-THbwCpk|?HiqpmOYP~*K=Lt1TB z$8a>kR^6={av()A!zo+&WPIB@MUsi4A(#1!BtOQ3iKP8$AErotPZCKZ@z5@bqJk(? zq@w#35xsz8oAqOpp&gZ1hzJovdrCXzVx;n^B3tA&j8tnxs4-o{RMC1SJf?@@bkS+5 zh{a^Az#0*weCnt)7m$j8#(~g~8O{*P=X9oA#WB4fHyvO4nVL5mLYO{77t&;A=5Q~Y zLyuk2a#Bm|q(y;bYBi!lnIQ|4w)of;EtP>t1jg>jV;8Ji5)JsTXk z?wZW9BiVCs_2eS6is0%|5Y5e9J<8Pz(N=||XzmQI9{P?#B)WPs$gE;Fu{7K}I1+s~ z$SjLxF=UnTNyBK0-#Bp6`{i$_h$t(6K98{4H9lJC;~yD!djgmA5PBp53GPl$R(c>9pO(l*bx} zTg7MVQQZ@YPmoTmbC}Yp>YJSEFqZGiPNxiKhU9aGcy8jzmLk$Ra2IXV>}wh>wmnUB z(t>Y$sjs045v*zsB-Z&Mhrw7hss*uGBI!@X{Mv?Kq${N9Vb!K>Y7ydmlOlHZ;{i}?GeDMWLqxpoB0VGSD&VHZVE11c^hY&O!{J6zxN-J^Qh zf-W|87p$GzQgcKuzb!C-Tg1XuYIFK^q2<>za{4tkv#PAzI_W!EY zwqc%;AEb9>O=U3Nh0WtEzkuGm*wY_wM?eccn3o&hf2QWzu|-%>FJRY2MaB^l_$Fmi z5m7}EDMN}#8CpcjO+`dE7ZJ@ZB4vIN(GQDAr3Z0&6c+?-QnH9evnXBsyPJP+` z%`SV@kK_P1a2U}%XLDGL=E0`^ zQ}}(hsh`7;69dMk{x$sm7{ca#z3Y(l;S3IsBcca5jL4lUI1HD{g&c;9=SmJw5TcPL z644XmV9$bWFc?|k3J}GU(zvm@29h{`3 zgOi3*ub#@pMT8OrMwRE)X-_k91<+JnvKrv9512Wj2QGaTf0pB7dYQ>)1HuXz8WYV8 zT6`0II4W%!72RS8F4WhA(xFWQ{M*^g42VVzdZBl}dY zHoPVKNM44#jjSr?!lj&+Rc3)PgTvAFtcxid6q(;SEu*4zK$`qkX^M4W=O#A1>pQTS zIiI%RnWQ#DQgQeOqI_#$VH5RDJHkeSOB^H+;e{{=UtLYZM4z#uTzx1c}`rE0AGA`IAAuk9}vScWy) zd@_0GCW_1jW|78z@PiFzIe=sxntOonlyrcvG5lo~&EckKwgr+YmYHW4h4BUlVYFjP z2q+j6LJH;_=vaF&Yo1nYE`skEzhw1C=VQf+13)e+(eQ8emk_GJn(hM_g!m_c^-Q<#)r*>0H7`*n0Vj%WPWPl+U;Y%M-$iA%wImA%q$Hu-T@rW~zH*iaJm`MGfg42&v3)&icgN z;LX{MArxtEj*=;mFq6}jDaW+tf_58eHCK^g)MAvn^WGq4DU<6Ii90IBX@&r_UEKh^)Q>&Zp$`SMf5zxIr&_T86{JaOhDP3 zAuXjg%Nn(iTs^`U5f=L5NZRGPPhNEw=015PmGVrrFw))=H0tvvuLXOJysmN3uY#sj zel&>e@}3O1FLoC+B^DO?XiLMAMGll47h?KYvrgJlT#SM5RrJLg3m;B-Px@O^j~0XSFBAD5xrO?7y2$)Dwk9bI z(X{JkSf=Ts^`H?$zzqKl!gPi-#iH8Acr4{_LI&zY)_@&mgjynWAg9AyBeCE*e}{o? zLCdPNAfK^M9Niw@V@AyhXBzJoabyE>KQ3vEwHL>6yGb1BlF55U95ZeM)y2^eLN+fn zB$3$~{VI;aMDqbt_|ma&MP^#Bpr6?PyL`m{>-w^vbz?4@TXvUjbhEI5%`K+uba(2; z{uah@_QE)RpD?oRv3-Rxt-GMy4zMV_d)pCSF%?snPqhvr18+CG~=EN&V%nsbktv4%IHA1&Ga?8UNt zH;CnKTz~YLu>cvx(I#MyX-;Oo<~?(q!UO7BRm>?SdQ){M^UCXGjzr8H(w;N;;PM*zI z74@%74!DyiEi`ssnwHi11qIk?$8`E=2w(wybtJL>n?@4*A0nJW8X~%$T{pAq)$Do; zyWV4D@58B0)ZcSZDUi+xpfiH!1~BQnB*4bvhef0293}w&EJAriA1&sm)~%GeE_~Se zXMLN96l8qIH!{BC8yVm6o#!&-1bZ>w9eJjAqe@MO^yI8k&0v9|SXV0EwF^rjPnf!L zpIF|Ymbp?VzGE@Ah^yy z1z9oY&s~vhp4&1tuOPhhOd(GDaGB2h{Od_K>zMh@IGI3-I?~wbC&*C(9rwuTJg_Q}tZ|7Ultob<^#ZA?4+YwKjWy)+)Wcd0}d(FB6? zhdF%=c{DB6v`QSxJvwW{32kv#AffMu#0p6X^6IV966>`@u8SmL$@ywb75BK%^~d>O z1EK<*V&isonrI|@ABf!^lk5d<&~6a8evK&CcR}ug?vr<38B3I^zBZh9&&M*+Oj6NcX#jJIG$(c5lMV ze#^|U3j(JnkzJ%A#;2r6v5wbVW2wOZD~9Mf3cDP$;1# zlm2B(R;~8W_D_|vbY9l~@=qB~R2eAwrwsD%W_8o8{F^7L46veQKI4H%Z8ybM?sr$Z z_bBc8{*9 z`#D}O7rESBvre~ixkuvl`g_)SsI6?O({_Uqyc->{=~-vSpjpQ)&v_fcf)}WnYrC{W z>8p>Q5uc8AdYR8ok^aNPChftXrOvzMxacB@qFVn)baux}k@3AW=d zuQgf|wvR!oX{7Y#2ioIvsfT^B?@K++wO=AqLPUy2L~TS0a=Z^GQbrId$SRF&(#StI zmh>~;6a0+w2}H_7B>N_!gNc->M9LvVN+nMgSw}>(h-fwu9Y)COPINfW`+g)59Yv(f z<+_eH zbcN^?^&m5d$hTq}VW)Z=&Z$C* zZWWpR)CtevvLEIY`xE)bjwLz(Z~F-uDAnVh!;8=34w1)?W_p%Lo%3_t@vv0PthVL+ zH^|=vFQH1u5TRGuXQcoy6yOB{JfCRjzmFe2S0SQ#L_=>I{x5)-d6{^Y3GfmDZW7=r zL_^PdawW^|KbdIgueKt6InjZ_I~4+qr{LC*wmuS0rYbwN&Q>jfwB_L0gV}FUAHuKL zX9>ICT#LAl66#^8AL%kX;+BRlyV)+WRbJUE!cIPjo~!$`+!z>q`Z9dzFz{2kP#T}RJSzL)d+3wV-# ze9(NI{GE+R^UmSZkiwnArz0ghFWVVJ^fHIcJc70%WL-p)H&Ftzn)%LEBlqqcm&9(RV=z>O8 z5*#6bD&QM^hHtbLzEN*{qt5t7ihFz`y*<8>U?1OQ{ChC}MlOEb2kYV6_z!LYj5PT8 z#$bhS3|RQapoMRwz{fZE2;T@k#5a<1TQNo*ADT*`p(?(66xBz{BR;|*p=#-`ibDQsBd}3O*fI2zTD} zlB$&WNDU40ky=~oBlVkO`3vKHq?YXGBQ?1{es=&am*Yp@z~u^DuEeDg4`%!HBN`6F zkLLJD^&F1dN8mCSm#cl`8`4X()ki)g0r?hgUW>~%ANe+y5?zNszKzTExZD9GclyZZ z-^n&rsouMB`(9jr=_6Hn4$$*HQj1^EOH9A=k=pwrZvWaxs`n*aUd9Wr;PNUS{1%tr z;qrT2{(#GCK7D-tBme#rZvGi0{^BEbQ-~C%Ycx`PM->tM6_49V@xA9G`WycE2a5Vn zT;9Z=Z}~`_@HU_wxV($Y8@T)(mz}u$3zzqB`8O`_ddcw&! z4DqQ{Ufmf8&aU22J-vEE^)!FHVEZbS9ln(9UO;qHsYR8Eij%v9F@^qTZALKoCl)h+(LFr0a^4QI7>!&yzW-EdY@ zjp3|o-*A@Wa5hAx3lui^4OZy_FB|SLY zz5xycoccd=bW>c6ZbSQbbgQY(GP(`L=;oVebU?8Yg%h% z?98eff2Ds-R7(vdrQBQXuV=$uP2=pg(CnFYvm3P8^^LP@>ez7C=dO>GsXuD2EiJ$~ zN`?UgQwEX?`w_qs!(oG^Bqw{ zy0tJGkH;2}S~#YFRApR&uJ|#Vqy2Cjsvv^v{HtG8{m`p;vdjbe?)+HX{q&`O1FT4@Gv zr5U!Z)L`364WGwW8l7&X(O@m_vV|>TYZbX^tvcRXy4_(FxtX@DHS_b>T4U0!HHNiT z%bNM31Qxq#t$N;C`lQp^T8*}?)%baAt+DCW8heN!fj+cSDaQEeXDMttPUZk#GA|Jh zwQH5j=C+{9?->b|yxdpUL8OFn8XR{I#EAK_*m5OCYs?MdB7i&Kt3=G93wH+qIJIyp z9?r=d;v-T=hKN*8J5Es_ih05a+*=116MSdPXNH(kxXF|RUWKpBlY(EZi^zAGMzo&D zcWscUo5=U;YN8F?@wJi2S6|9C08Y;I;N(mN5vskty}fNXxQ0zB1`S2dMb=XK-|dvv zhALXB94%FP6kG+0&{DogZ7N`*D{g$gMQA7@)y#>1bT?*w?sJaMWw%?=5GM{2QF{n@+^_>wnBE` zj1L|132y#|$cLlveuwt@J?^{)SKlA;`%j6cj&80!xVNW#$ohD+Dwzr-B3d$8mFW5> zTJXr?f=x@6 zG}rojd)TXH>tK1+t|d_G5k{^3wf^Stx>s#^VXg)y`??cbj+cx^IO)Oa?IM+K+~dl=(Ke$(eAp# z|A`+gT;6beQ=qncRd?f|u|&o%)ZN(T~50Eq3Vu+S_05P$i=~ z)bsgthZ5YO865_~ymVZDI1FkU7cH1s*RZg@v1XR(Fwk|h)hEg(bK_nX2C*};4Py3F zl7Q_X7Qi63e%~OL;~+Nhu27c)Tn1O@zzl0XmwwRPhBc)hhqYaFg6=KDn(hR3J*JKC z=P_-rIi?k}c}IP_?Wi^$7Fu^C7;I}lkUJr<8jcU1V8tIFtf(6>LbDf8b8W$9QVKVd z;yIbrVr3|)9xsEaM=cyal+?I#GWq;1SW50G_XXS9D{I?3PAeE{%!HO$aQI9dKHwRv8EajZrZxqCyiWr$WOK)hhN$Tx!$A(a^_U9#UHie zw?<19BGMonOHFT&hhx(N(Lf~Dj-UiICz=c&e2-*H_dRTaUPwAc{4}JcqFSmlsijik zXnPVr#Rpt$d>;r7BRw)j;on9KikJTlRNdi(hBh;rR4KIKEEXh@ZOQ0W?BF zOU5GWwZ!yfDv$~XS13Bw6FF7%a)`rdTLXste~I4*Ycz8h1u#hCHSQx!%D9hEsWto^gi9HCaA^2)e!rXuXJWDsVnq!Yon+v_5NX`U z*^36wLj}4siCFj>J_t5LC>%bBF>T{8VoePgqnn{9MTPh!6(OUB;|!%Rf(OB=n^!7e zZ6r-w$#?_NnF`e5po73b2jZe&CpB{p9&7lLeanz8uSH9RvZBU^Nu`N;oCS3#nyhM% z#o8kplq7xta2^&m(CJjZV zF({g>sp^Vqsj6<~TJ>S2x^h9ws%AUf*5*G6ZKRsGOU#y6kDa?<`Krp6HS?JX;tE+S zkd>IoCRmXzTiC*oK_%!rZ5t<+|xVamZivpcU&B`zx?*`KZU>av)nq*=c(ix6Kv_us%=&KTJ z-Jqy>$+Be&k6GacF)QMD6LE!!xU@6cE@5?7P=;?m6JNQBZ-`!H31!jT=2fe6Dd_$t z;sZ>?rSU{c!b)pgSNs4I-yw2;mnJkz?Ok>FNOaQ#6KSbg$fEW@BGAr86I$-3c&x+y zCZJ`secBtGDrHNQlWs$yNbN1bI7o-GqDgC;+M|l?dB#Q~@50qWW+d zr0<}RJ_UGyiIaL7k2W{~wz0lufe8mH7*E97!V%4ws2zuC6rU1(nZw`r5FMv9*N$Qg zF@jwuu|&1!6Z?ZMB%+Im=wc%J8WCN>=INxs+Q&?F9kvb;QHqGVFpuRk1Vq4~cd(tY zHa+EJNsyVL#hMM`g?%FI&RG6Ej(=lAmVymg2v?baKPK`&{QSEDo6Qb{+vOmB=U{Zk zWFEwUED<=TTgBXlZ(d``zR@GP9}TTm9MakXU6E8B8g&LPtnm*OdSjXZ55pUbMMnc- zM?y`p>7y_2j&@byf9%_+%ta=&tBTCutQ|8qYX3CmaNd}eS~Qs07*B;`(OqcQ2DGqU z<6?9Gk8AN*umduT4{jRYDmB;QRw?rd)K6cpC6eJ-6cb+XzVRw1^9Br`g8^gW4HOtf zl)iwmy>oq{%@8kRXcDKq@RMVh@)DvhO1KXaUL&Z^V(LLc6I}=le4{huyqwd!THE8(xf2RCTFonu@6~*01ojaSG02%R-aoCpw6#56$+^-LY3kE-lvD2(w8ySoJPv1Gh0JvO^>vtS#UfB^N-n)L4244(l$9!kT5h&CGw z5TybB zqKDL{zl6(|J%)mXq{3&UKnErQq4gH~A;|d*-$81w9l~rQ!)HE-2uIK>*a!)iGV~W5 zFUNUwbBB3R^#PZ;QVsR*^A$7wAX*;G=)mX_O~sAz$>3Uiqe)AdrY&KLwtz?}VuJ$P zu&Jm-$`EdHF{1|im)B!cFsun!Q&k#x0ie)FMd*a-%GyDJ7V-7{ws0d7JQTcLO5Tr zb?&@W*KsRnMOW9)+|aV1anUKqEZ?|h@ycV@&Rrf^IIF3(bMgEI$H$kgTzUA1>5#eO zquMaU({Ta9pHzSie8AaIcYJOA!ZjzXT$yTIxI~+~^!Nphr>;#Mn$j9iUB7st7LO*o zL-X1@Pm3IX_@{a_9uqdJJ}HH|i^ST)Q8Y9h+-Pik;Ndr5y%U;iVR@bY?A2kkBH)pa z-W*1cb+g3-%XH&ijtJlH^0gih^Eo4N&wfl9VjC_KBJ?gW!M%;0#n@F$m{BOWcyRIJ zQh-Y#E=9Ots39LNDlR3sVB|sR8B;TTU@RgVFzg8f z29F=b-)~ZIpDkT7WzLK}DDwi?u|*hUN?7kIL{rD=vB|@#s}fyR@mMTU6-~vfVu^NJ z422FDYFuF`a==jQ3PZ62h8b22N2S{V_Ln}`4zs~v#Av6&of>!N!_xug3UvfA@k8HC zk1^xaV17gEz&c}j6L^F_UpQus&JrAyV%nuI=QYKWsg^*ewuqMu9pl5G+KqQcRBx!B zF?sFsV~$>Y%>C1|zRBsRa_jj!I-*z_$6m<-=!5t>7!-`(LS(1#`_PqB z4cMb=YJF82C1tj!S@Ghg6*cwM_0h??aeaYezN6=YK;x7k6g;&o+@{qW+~+mjqQh&d z?$=wOtuOEMmTtS@t%Bz8>SOg4N0FL7A;$~csoM9IBD2ukZ{PQo;`A%Jr?<*12^yC% zg!#%axzCeYs&DO7^KHJ`vTR{X-?wy`XKi4v$sA--HX419iA!G^X<0MBZw*S#mx?;s zxp7na;3+d-5tl=z_IYox`CjSaljgGnt^7+COv1#WBbG|WW2x!gfk;FPRkjBbA&rS1 z*!p_TI--KVm)&o!{plb?&sXwUp?b zQlfK9iOwq}I=_?@yR*@P7)l-+WH@V{97HNTfs3KoS*;!)MCJ4|Tpq#YVO*>lmD!D4 zAtDiU(sdMqph-jFgcfvdG(jQ_6&wh5xHi(DV?wc1&4%fn>jF?|a1;R<`U4Bl_~3gy z>*XHohb6TH9B0f2F`a|G##3stA#A}2qUqjrd|0&r*9b5s#6}F+3<0k5>ZyqEsTb}y z2=Gh+ZWQ2I0z6xQ5A&u6^f|))!v**V0X|ZIj}qXy0z6NE=L_%x0bVG;iv)PF05=Kn z5&>Q+z())4G68ND;1&U1F2E}Uc%=XzBfzT!c(nkp5#VD5c&z{*C&0%G@CgEZq5ywM zfWIuj|0lpF32>VLw+nEG0EY$m6aii*z!3rN6yT@;#{@Voz^4juLV%M3oD$$J0bVb_ z-2%KpfHw;8X#)He0X|)T&k*3R3h*WY-Ymdp3h-G1e6|3eBf#eh@Oc7!z5rh!z!wVe zMFM=W0Dnz@FA?Cc3-G00qPa}+i7peyfh_`jxd4AdfUgkXD+TzQ0(_MKUoF5}1^8P6 ze60X)6X5Fv_}c<}y#U`Jz&8r;cLew*0lry)zbnAo1^5;LzEyy46X4qg_znTSQ-JRh z;JXF*9s#~rfbSFF`vv%W0{ndeen5bKAizHq;0FcxAp!o80RLEkef*=;{yDI06!_fPYE!bIY^U-&ocu2tN{O9fd8KW|3ZL&DZtMO@bd!vf&l+Y zfL|2gUkmU{0{pT7zaqe|3h-|P__qT5I|2T^0RKUNUlZUz3h?U!{3ikavjG1^fd4AM ze-q$01o-a)jNE=k`~Opb-xT1t1o&+M#`Z?zw>t#*T>;)H!2c59_XPOg0{p%Je;~mB z5#SF6_#$~Sf8KP+-p5`-&Or82-${oG4tpmZPB>b)zyCYw(8Ag8q;0Ch-y!4! zWFOCC9;A6>pYe}*kUx-p<~`;yT@FiycdmTQgFJ-nbLs0Iv)!(EJ&otuKc(^f>aQMb ziD#b||LUP{aQN4M_0Xjpe(A3sI*-G5{LRA_67jk7Zyqz8@UFjk=obdBa2Zb9n3<9+rI%pK)(^*dir9>q~4_(RLCYtbuhrY?- ziEnt=f+s%yH#~GBzu)q1x}3+o>!EM)`yK!CV0ywnkNqe8j{2d8w(KYEPidd)UDaCG|pgGYPK_Mbf3OV{!Dr;JXQ zVd`iv-OTSFGCE!6%F$lBmfx=$?Zq*u?DJy*|2<>UwC)|_Wed&tTsziFH|Vd^wy|Cu zn94r0#--n%JD3PSa-PRdu`9H8}M_-~7$=JJ(&6hCdPDKU|x>f86#o{HI&f@Vn2Z;R}A5hEIDT4ZrbX8Xo&{8XopW z8ovMUX*l+F8ou}6X?XnmY4~jce*c5?{pJtT@cAF7$Hogj_Ojp}eBS;v{Z2uz*Nh>! z>CggGr))nW4L`mr4aYVWn0Q{?RA7$1Pfsf}$Jl446`K0)km-dc&I{+K;a^WLHt9B2 zr{S9?sir=vyihgAw5khL`VJpAW?ZP6O@3%?g|ky!H9_9>|8 zC8B2^6%oO|C?k6I(LRWdwlubg08U8*0Rr-d)>K!`VE<~Wt1D~k>w&G{=p_qQ*)=y7 zWf0VePzJN#;M+7%qThVJ0_M#(PCju!1T(b2f??ed^oc1!Jp>C@tb0a+dG9tfQM4O}%VYxs?bd*a(#WEjZ ztwBOm;I{jR$cV5|AtCa)MKn=HgjEg+(NMRDj+7B$i9|x=cZ+C~j0o#15~8ErB6?Ux zgvA*N(Po#3DlCYwvLhm@_@P@wkI5y%vXF%65x0n*kP%@`Nka6vTSQOFh_E0fA$rm+ zqNijL!D^O-=qcBT9+qScOJOo1n~~pQ9x;7g@tj;WtfNVYo_1TJKgx)(2qz(W-Yuec zWkguPlMub`7SV??A}s$&h<3U}H0x_JBCH*Xh-Q7wrQ$zoh}`{HcoY#GH6-qCggok> za`$7^QbP34>)j!mH~Mc9A7RN;L^N;oUtJ<~YE*pE^e@~K1gvC|~(SKcP zkwt#lIKoP;h-i`DrHC{Qmb)Lzydt8e!7jUh=@~L2tPzWdmY(6VjXJ(1Bfa zAIpu6$O{qC*Z=3Tu`jZX*N+Nr-;q zlC$slR7QlTA_>u_E)m`NsEi09Ng|>bTEwl1h@ShSOHKRy zT)D9k^d=&De(u%oO7#4Km{c`H%t?qAL|h_TDVu%>x04X9{IN?!T{34QR!>6I<#Nn^ zVU3Ikfqo*Q7uL8OvtOMpt0P1SiilpF?b7snb%|_@BE(Qaw8W(``s%x~*AMZD5~6o) z#_YKk*Rkm6M^K}I0BZ+Dwc&VGqKmBofQB&NOYTobV zNjpMWMO5>Cf0Q{hxbSv)96%tggz9#EKyiU;Y4>uetq_MR zqFUO$%xwkR3xX0Vgz<`~+6zv0i|Wkt2d0 z-T8^kqKH8jQQi58YZkqK&SO$rA%s~(b^jcF0CrKT2j|Fh6huIas2-g2s@rD&e?!Jd zr9uF;i0c0h8R-_)ww+HODGq&zzZOy9xywQ3!8yN^P$7IIL{tbK7g6E4OH>aY|68e4h&>lk;kipx6U*jFZH3Tv5fz@hM74Uz z+#AITBJy2Ch376&EtvQE{vs*_&Wot<+$E}QJ3o~wh`4(Z6`s39wd$@xuZyKZ*uIDg z&t0P0wo|PWQ6cJIM1|+BQGFt5XKWgfQGMc8J8#?hnABF-b0DL7%xzmuEL$v95L*^R zRCw;Pg0n7*J|eaic07ov@Z2S;Z96|1CZfWI2@w^ZyF|5m$h?4v3i~ZYRCw+Z)o*So zDi={%sv@GobC;;L?fe8Oz|EKu>~s-P;kj#6&q!^BjWRN-XWX{cyp=zHLM#>b z*@&p{+-0fmpYxc+4A`b4qQY~RsOGKwd9he3?D7#&;kipxuTGgXRYZkNLLw?WcZq7- z&S#}&#~vdQ6`s3B^*0F>wkXM{{^lOlClV^`aFS7d;uh7!vZi{mt*}8#M1|)rD|mWj zsHD8Gze+@f=Pprg+xZKrg4muVqQY~RsJ>Kn(8*#2vAat|h376&ZQJ>wR4Qx^6H(#0 zYgBJasIa$8M)jt9RBuVBur*Ca^_E*yYd?5i(m2@JCZfV~mld?SbFeW^L}j>hT+Ak{ zE+*`&6Hys1CKsrl49hbwY|9f-JsIBVb~a&kdt+Chh{|w#yC{{_r;km6A}YhD?*f%| z1r2)&MO4NLnhR9cB~)xl6j2#Vs4h^g{oskOi86>CjUp;Mcga`Q00C@>6j2!g0xn8r zjS#_pN)eS2A>snnww)|Tm#OHn9aBVw=PoO_ZRZY2oUxlzMzzDOIB(mzL$cek8PtNx zz1>bysj!z+Mn&#R^}2)#TTx|HujhbDsvvfR=N*n;YA zm#Ai47QaM9g)PV;Dm-_IYTM3_=ZL7VgIPp{=k8H$7ExgXv<1~>*QjCmDDm-_IYTM3Fydo<7P~x;-6wh6vnpn2FKtzR2|6-}|+$E}Q zJ71T^cH|5YQQ^63R6C?nA?1LKYKQw$ktEK@SRkV!x8m$Azt}If6%rnZsPNo%1xZp~ z$d@3Z+P0H&P+o(@QX$=fjB3YV*QMGajqS+RU_s?}Y@c;me2Z8rBzq81;koNleJr&V zaz%)!w(b1buC46C)vwZ4e_JdSQcZ}c@EoNoUfmr|8RyS9ZFxg}3IhR_t;^!A$*NR$ zxU(IJ6#JmU$tKp#Q%G7WmI-Mt43t>F#&aD}daGj5u?to$i3X0bL094$q^mt_hf#WpgOxIs5$QvK z_9Bi}MKbkNzz%2nk(B|(wnPpRAUt-QUg?tctld$y(yO9QcU*4DHw61f@~Zh-R#sda4V!gG{rcy~A&ighQu;-NrF zOCpCWsyR~syQ(uBOvIA0wiFuU8x}eueq_xt@ME;yzq_ll6-oN5Qi(uYTR7Mmhz8oV z1X`oYfpAqY6$wSEq*8%)RY;43*K3K5a*-}|C=!zQph!PV>CHGjH`Gq09Fqanc@D)v z{vfe9QxjS!oTxGyI;ppDj?HD;PhWE=1u_?*6hC`FZAjZ0W@Zh`fUgN=BKWR`J|{MGgui5`m2k)%8-jt%R?!5Ecm{O_MqT?5ZrHK2b*22hIHs z1w#@ov0$?k@ycKF z!>rT5Gd>wf2GfIv__K=~Xd}0nNPB8~q_qn4b;%C~QhCV!*i0308U>Nr3?(^~bJT=3 zZH6$mTSgD3rkL2K%?Ktk|JF&&kW)=81#6FB_pY_a0ghF18kCXNO)5^CRx9*!eyU-- zj6`IWD;-z`Y30PS)P`c+(MT*1a;=k{I&FMrY~OS!6!P1Ng@Sd_mWOpwlbO80NMci6 z=uj$T+7nAPHkEACa#WyG#NQ-40`YLPoynqA6mE1V2-5taAk(-|&1PyMl&lQStf{H4 zOjoEq5^D`as@TDT-8dH|R2d8_lc}Iq2Pqv#J7JRhe7RPSw|4_m?w7&5I<2 zC}~e^gsFNwcOa>&`o@}CN8S7_ho(WMLl9JEM3}0tcdSANCU9z%0~`@v;7~LqUPRG; zaD-m8F@c#4Gtu|m4fR~zXH%h5GWP~k@yV`mirEXceRI|9^cFoVnF=JT+NwekfwQeT z)_!K?#PbJrCfNw%jQA#pf+BG!3Ob4xv^*G!V?>X1sCo;mKoDU4^WMlGy z$y6+%fuq_&RU2Bh6b`ou2eqWjiG*MLeJHu1kDNc~P#C17MPYu(3$q{_GI8$26{(?d{Y)4ErmfN6EYB9d5+PPN3$^K3^=*J zq-KVrqW+1c8e$EQZW#ps_qg7aN3pRX*)|YEVVyn{Y8z6p0AkUk8#;G76dw7ZQTQHS z_=9v+lT1eP92s>zkbmu+W?x8PjlwEV=q)`uP+L7?24vds0A(`?8}z=(u1T^Rh-FJJ zdQW5nWYk9CE_q4kJ3P-W!qv{kyOa9~X}dx2>X-D^sOx7tW`8Gq*E#SMa)_f~-{J+E z1Q$x)_R9>XVq`GSoHPTnnxk~z=A}EVCNvO|T2ZqgE83eK8W9QCQOxg1jo6x}RL;)7 zl1{b?GQp#e+j${J2Wo0-nU0;|a*md@jbuT*)}h6aiXMfzj~Ax8U5l;P5{~1#WUe?! zD;5H>;kwMBY)FldvOU1dHdd>to-wmJC(reC7iAFZV`q2N{o{dA;-G~z{V3Nj%c8o+ z;U5o-a%cu!S=QG$+Z}do?t<_v$KJfyp$BmA00;)Z7G-Aj z=s-#Q2U{{t9_7~9g zvHGueC?F1FKmmWs3phGZ(^v=Ri)%eQt2-PC1p|ptl?yWnhPb0Irfligi$vzZ0TC$Q zb&WB;B=+^9tjyC;J=2kSu5f4&oI(MDw>HKY^GtJeYsnRI8dfIOI$O_9s}?v717*6C zmuWP2kOf_jy@%#d3p<&vyY?%q#csiw94OJ-Z|U8F=UKa@v8K_nTkHr=S=iDe62<`_ zAbj`cIG;VW^kgO6ki|FmZ3lk9DI*|w;#G0R4>RkW`!R!=;>a3VP&(PkIQRs`JDC@6 zbTCrc9tpP2s-8Kkw!W%87>ZT}V@}i?vQW=ZA-m41+rB*}b{0-zLE*aJ);kN&vvyW} zmd>&xJZ0gcLq)z^haWc;*1^?cf+{}-l0c-l)Xc1 z8uA!#mP!L14g><>CvGtaFU>yCHPkqVWNdO6Z*b}m2%h+d1mmPJ$xt%K4w;BJrS3pN zt29?d(koxVScV2)x8GjX)Z0-`Gwu05~xUqz~Yv_tR=>8)nvs z)|VU479t&44qjP@0RrtG7I!yJ-2`b$Z?Q?SB`$90z29@Fgp|^e*4N z{qI=`*Jp9#*^Mf7+h3F7>~R_w2tN`r2*1YS>>d4w^;xVKr+6zI`2~W@U+H4JHhtat zhW?AU%7)4*5CjL1p=8JLk|Ew|Mtx&Wv(~EIYU4C-!Wn2NPAe}?;{dER`Lp44iZsB% zY$)J5UO>a~mERiE%xp!;U?yyF7}s!I97@<_^k|@_u^y`;IV`JJXDgR=E^IG#H+>?C zJI<~{!A>k+&&BTicEw94N-yP-|OZ~bp4%K z`?9{;*{Nhlc*>&YD@4LLJrRVv_TRt=<9T+%d03)#+n@fbNEk;og7Bq>=!Ee+JK-#z z5W5=JZQp*FNEqirg77boGzf1$%mv}x?Sd%_m)#)}#vzm-{AQdt^}=O$WF_2C>l}x( z$}(gk4*QsAZ~UQ17$;tW@TMDd!gvnC1ue0)i?J&}-iXj{K`Elbftf(H`GyU;b(!o; z#j834;Yd}d9?x%CEjMWlwZ0j!kU`0Z&H9$KPZno#g4_`|>Ltf>spR`vu?qB0vJepK zfdf8)c+^dLJ^GXmRHW@HecrI+wJD31Nt<(Vb|}bv|NFel7cFC(bF)}v&ep#j;j*O< zb&K`GL8T!4i)VGhc%GftvY3K)gzN6T=OK|WPDKUbmtN2b<9SxX^;wwQj_{O4%k~oq z;|Nv|uKm<(>ix14&N8#LBV4!rddWG1^Ik#thLbiLLw9!POntSpbH29WvBo%D z7KHEZ)CuEx)*3g~IQx?A2$wDWx=$pGlWaj)`JPS~&$AM4$cw8llDwrjHW!44J!%lX z$c48wkEX8MzFo@Fgfn_UI5GM(-pAWnmL_L8&SD$cHT9H*%U+S1niD?jK%Fq2XK(6S z=cRc&!evV@eOe@p(}z*x`&x9uc%Geb9#(DBHN}#X6-OO|@S|VS3FCQI!uh!3o31I2 zi#5i%${_r!Q%u5f7ld;+!OE6iDCIcAAx91HO{g>%Z|C4t|^wp3CB}|@GoC631=6l#ysS>>6+pWvBt-C>4b+2{R)#~ zJkMU^Jludy*A#0aVH~`T8c&>H64tU4&aaPyB4M2J4Z_o>nS_Hb2JjpSRi%V zZ<3ZVaOOM+|K%o~FrK?0oV!|Vx~4cR)))uegRt^5v#G;b31{2ql7XwGgAoqcs1yEp z`RT^U#STVr=IT6buDXBRaEw^v2RY$o-_!}?dDa@&=O@Pzk?^Xo=rt}m@(iQKk*tIp z^D^jfI8h}0_~|;~*pGF>b=z+^F)QKv{M2HbNVxtCo$xcSn>B9BO1Lo(Cs5Nh#hoJI z#hY}(n`VC1XlgbA&ca-IDTz}=!VymRFN;mWr(~~j9!n)nTPnIl!f$ToP5mY(yrqI2 zeBxN+eC+C`Efta+m!7E;{>?`w;p}qUkk81qr9u*?g=gu6KOVVB@8c~M*~KYaaJlWs zwWUHDGEe4&2UVDavk#fsLR>NsK2_}FC?_15W)eO%D|6-J18Le)krD}C&k0u^X%c3c zLb5Pd?u*S$TPh@je(>3PACEuXB%Ix#&u4zzw51{;)_6Q8TyeHZIN_qHbDujkZK;rE zizjlzH{N0r&OTerCy=6PONC@*ZsCNRpEe0+w=%QE%xB&^%lr=~d`{6>24NSz%-TE*`mKfMi(I|@ z61~RP9CWr$cx&PLS-HAC51XrLYoWwkqb}76Ke*pH2I1_?m6uC#ONBIB{5vOn*9DyL zmWu4N#fE(5PFo8P7n}MUm+3Y37oBU=`0(saogd+|MZ!2H3YB9ruuw538?cN+h`PI$=QIpHl8+1H&K^3hIPDx?AAZBF>v z)YV2GXCFYarRTF9tG84n#ioA$1HHzdc()palUbWOTOf=r;jM)ih=iLz)CoWKS5A0q z;RRUv#J6)UZ9;%pgZaTu(&)E^N=O+;DfbAb6{yQDHs^86w%#^JmeV|i|tToSWPb)+r|lG8rEr>7M%p6fdD zm#jf%X4xc@A>!I;V^+3(H%*_S}_iD_!uT6nIglP;XE6aH)WuM8PJ*M&}UUdpr^319l2 ze4_oYrx!C0y859%Gr})@Pd`vuih3+LJ`fFQ8y19<>+Eo@{ons;#mY2R>o{v4)^XxF zDw7GP(^k-%C#kG_KmEabjKeK?U|WN2q003$D+6u0Zt%;NpVn!gMCFBgp>DtM16HV7 zLnBsdU5Qv++qG@)lMQTH%!BV(6rI=wRlJ0E@e)prYL$W0SmPPkD?4*dm|J81)NM7L z_7TkBMSP7Hu`;JrRSv>&Ahri*L*}&ab=1>(_a1!j|5*3xDS=!h0?0kro{<_ZJ94M( z{pF)en2=0+;uBWj(Se#-vskV$w|Rx?g?tB2X(Hs*08ZWe#tV9xe((!Vm}TJ(#$flO$4XX-bjhhevbq*Yli5a*Dl=)a)w*^n*8~%ZZRTgE z)_Q=KDexP;Ow)t$Y|hpkS}PkWr|e)a@sb_*nqD%V9n3`rs@$c)COcSmI=4FvgKxe$ zn058Jf1Aj_^d2wj<-DjuBD4JRX6o5Nvy>=9U9WOz z)38ma8o!tEWo9t}|u4{YqzqN#8+nM!m4>YMY$ zdaw(ob|n)gNa^zqnlpkG@9KkRg>l>fofdEsAX<>d3m|@01?#G zit+=Fa%}r$63UWeSF}{F(h}>n1Uu8juGLnod0!Rng`aNKi+Azl%NZ^_N2`g471<)f zM?~}_M|9v69T7e*5fw-$k3Gc^HJFGB*vVs3iJY>yz5K9Vr6pzGW_*g%4TAlpf(~?p ztbmA8ZK-%E5%u);_Kqa|gYS{lT&qxz5BCeHhaH($Mnv7+-P4n?;JW1WKrrI=heMPMC%^|Q z_-%77s#{E?!f<5;)s9`P+4)hN8>HQ(}zZ{Z9- z{VfkDrr#2&-3#~XVM{Xd0~_-QnA+9^?b*ckzlDsR~25D{g&eZI-ccy#X-LtDjmah#Y5N=3-8z2xq-jEP3A>m7m!3hBp@&NJy z0YV;-2XOIC!o2}PLP&^xfB#d@?&(>r1R?&u-`BQgX1l6RojP^u)TvXaPHnVv;iQ+9 zYopF}QLkttVUO@nqEQ!b!7s{XXTUY{BEu$=0Tf(b9x9#(D?AlN{D?Pr91o&wD{41* zL3ZmQ*&XQ0>*a57;1%-s&p8fVf%Mc5IWOy>j=lIp&db(2FLE5`A^C5M^SE=xhn&sp zsEaQDkh6LHM(6R(>#zKf)4Or#Q1QnnN$OnhObwy%I;sp6s)8F(aJ?!>oKIy(blEG? zgJW~grHsF!(cMi;5C+FzSf>J?A)1k%<3z&&AH;sJQ2?mpMIzFd_Gr z%bZ>c)VguL&EsT5WOl5~#DME`=1nagFM81k9m&|Z;_u7qw5x7S#aeB85)*D{DFxYC757+uu zdkz&xJPsR6JR0fAq|k~pg@YXV_vP+=M^X1B;kV-Zk4}Z;W%{D8CY)~oj8G!p9f*RhOn+11Y*PS902QpLXQR@7&lWp4RPGhXx9#L?4S_@VV#Dsp&JSW zX5YbXV2BnQHJFXvzz{!SuEc=T^V%~Ec>hXu-N4L#d={4G6B zuhR_MLDCBSAYmtyW~(00vcy~D0h?Q4^!E!K$N6=~ael*boFT_?upIblQr(=Ms^d7& z!!Xml-f?=~;5g1NIF9p1$LRsPeZqlo60;!97!cKSzFF<2ak3 z4=`lv#fK|Xw#n~;{5~ze&mz+q`9~j$Z*ZUq5w_PM@gt6dflAMBTfaYy#m>c!)4M*d zd9TGEuXCKPH&=#s zmCB`Zsd5(*XOT!c>?!;?hYwG`o5r7q9jEs>{(V7ds9Y`=%R_V#R1>C)#9th1$8(jN zk?lr&+<=e0jw5Xw$Nj}|yx9#9!D=8zk!=?~cH(0MAKUS9Ek643@#9uIpYAxllcmyN zjnhpagRO>_)WfKWrSIUVS05cMmrLzR zC4Zk;?>LQ&IT!X6+l6Fv51ik3ZTN8gA_px=KbZSB&3U!E{npY>H0;?mUdQA!#@a#L z;#I%y^BR+_JbA9V)~!-kPe)ys=(-wVH3zh9vfaGi2L1R)&e4o3HR#w+c(D;yy+$pk z3fnVr^9H*LQ^6BY;CBc1SLrJJ*3yn*(`&VO?VNRN%&$W{=ct3>Hfb-Z=d|NS%TBxb zBD)T(J?*EXj;nP$VE6Q*8ViHQ3d^g7*|osfrTL2WY<*;{wS-mL0`L$@J{!Ra-1}_1 z7Ff)zTFm^6r=u;G>9!o5-gool{=0HWWgo2Hyx9hS!{c@na=>4z!S9?40}dXEMh2s> zo%q4L`YtBkT!YL-80Y;GB)GKox`9=Et6Z-r^`uq$*xL82gya_T4IDgi0$dYrFE>+|yWa~#L{UHKdKulLH|&$WJEvk~yc>Y>!*Y<32FoK4Qc_ogd7&ZdEP ztaFC&_g^;rCM@4%Ot{Z+Hhpuk$C<|*Lk38&!PD*#7re6*bi+G~tC8PIiak#6rFWbt zdbL_H32EM`J5KM_cbq873{g8MsusUUAktInaW*|R>t;Ycs z$RN8hzvj#Khc~l*UUh-9gN=5)K=tlFGIKZmbvLC@z59>M*!i#@iv=874z{kKD>TV3 zMr9va?_@~M_C?%FIBPD}{D{@t0o`}O!hm6OIcc|0d;eg(5+}SVJA_5;fK{p7-Bj*w zRc;UP%1^pG4DOa7KW`zr;WkO2ulM|KV!ORQ$C@FW)zpRdKf9D*~g>AulrRm z;W68X%VG~Uyoj^g+ForpT63Lj&7j~Oc81y``m<=4-owtKJq5{)c2Wo6-_2pW2mPN( zwdt`hzK+^No&TKtHf>M0X`&e?JSqyVD+)voAT%KwQps&d*CMhx&+M83H=V((y*m47x}e$UgW2f8efu9l*}J8p&2K>dX3Ei^SX%3jv~LtRWhbX znY`5Sf>^zWK%Yx^oTwL&+Y&|cM^F)?1|fT6gZHH3dTHvf!g)VXbtUv#RSg!S%%a7EbAC|s1Kpx*vZzbL#P*k6S|r~c zbAxRbf~ZGBz}}G!VTlK|P!pckh9eR&P<9Lrf}V^1sLw zeB)||iyddvt?Qsk36`O)_TDS2JZKdc8q3XMYayB|)~ZYQL9e=!G?ds6Z}h9`_VM+O z)B9ZVnYkVNr`P9X*?XzubjDakFV+3|rWXuW!$7lw^}59k2ciKoH#vc-7FzFVsi)q9 z{bl}$H!VH{y=8*<2f=^0)JKcrLV!qWyM+(^>N)mFR7n+lcA^abuUl7;T+e%-TB?ks;_o3~B< z(B5_ZMCuFzsn&@MHBWO~PVsd8IT_LjK-Q$2guYw|leiTo0+?zm#EnWIdEzU33MEm+ zMeLu>x4lRwK@$1%%~mT4Pp=Hl^MFU5<{N-Ci3CB_1~g1kv#xA9v}W*ItuSopQ4L#- z-->y4aFJ_KgEfaA-KXH8sztw64TB^K8>zVo{MO(#E&o*!uxA5zEeF+Tr9}<`c+O&+ z%kQ%rr-ow3c}tITqf;5K)T?~guF)Ok%FfZAi7y_t0FGS4XQgK0I39xr6Vl@{tPPS=+s{QZ4VUd)3{eqdRwxj(X+MxoV|8>eYAd zn%lW+ZbxnB?sC2EJI>|r`yVf*xqrcN%D=Rs{Gtu-Sl8pMdr?o1^Y+S5yz*<)uX^*; zZ+)z=zP77yWY2$p+E@2DC!X=5+pc|h@@*e@%5T5@{qH$A|Mo8r{oV&&|JUPvuXyiA zKm49=-f_{9zS}PO^BZ5fchlKT8(;E`^50xF_!uatgvXZd+2 z+Mhc0;NQRhBS`^5}!!xBrR1|69So+<5IPU-yh> zeSYI_f8-0p|LqIk_`_fSg&!|{`;HAyec|BkfBn!m`{mUa~|7utByPtgZMZLfF zcemX7=rfmZ`_*^${=r+@PrvKCuN}Fr^p1z`dc*NeSN+rf{L@cY-u<_~`m+0;Ik;|p zkJCexch8M>HqoX z*>L$YFMssxZ?sN4^!^v$%Kq^6*M98_58v>qzxwDsk6rSfAKQ2K;hTD{zwDJy>%V;a zN6rMdmEQEx#xH)UaPjhEqbvJf!#?`*(MMnN#5=0L^*g&Ouh{orxBbzJPYr&Cz3TPP zef&k=NW9N~=zE|3Sn<+RJwNrj4{rH_ck72fdjAub|JqaD@OLkI_?Iq!|BF9&pl|A3 zWA0!7+&5l6eC3IM`#|{I>zChq<~y(Y@Fza;#ee&ScmCt|x4rKbbFbX|<>5AU^Xy>H;J{mq4ce)F&X)q?{!9-a902Ve1Df9ju4ypvz^u??U7@ppdbJ)gUG zZ_g*cy8k!#{mHdG>mGW@`Skz#v&!9n`M>Y*-#Guu@`qnNebLgJKfLtOpF45cZI6BH zmtVN-`juc-yiM~^Ih zf&as&ANgqY+duQ3e|q;%{M1G7|6I~L^R3@6xqtt($#0cLU(SAR@4p9^J#y2PpZWfy z-#>KoBQu8{`@8pi?^gC}SH0M4{o}>EPkvzcfwx@uiLDn8@0m_s`rdcF_5&aL(CO#= z%~gNC`41nw_o-L?#%rJP)VG%1-+SG^fA*{E9(wTU|M$*!EIj?G-~Gj3-_rZo;ro7K z+dsD3f4nQY>x=Iy-|^+zYyaRofBo|3uD|H97gpE*?hV&G_^+RT#rOZm)aO3^%_}zi z(Yqdg-ur?hubzF>+xo4~{?Sjq`o^z5TIzY=<mGWr=ggNr{FN^Z3~WF3 z@%N6mocllXJJsP!58P6}c4n-8<=9tW@Mj-=!-v0g+aG=Wdw;m;8(03~^Jb^M^1w5` z_Nf~`bny+Mb+v;*F;-f6v5SuV{>Y_woOB=Bj_b?Y@65f9dsw zO{YKizRTYlzxSa7fA^KQjC}dT&wTCMSNzH8JAdW7SO2s-^jAOqx=&A{Cw}GN`+ng= z`@h_G%@x0Q_A8^aUwdcu@@mh&eBn9I`p7fBa>cW+_=Dek`rrJo;a_eE6m;=bl1!E3Tlk~cS z<*KI#o1*okRnS=uII#B#$2>A_AzdI8u*0v7u%3m9Q?5dmwpY;3Pxm&W8`$`d7V z3-de(%;%C~)oXCQLQ)B^#ibIkbV7-Sx5A@cttd=F-PNiPDLF~RwK{?6ABC1qH@skQ zDd8<$20Rn+giNAC=-)}lao!~R>lTNszx2Q(?q2!+u;XBRj-DyG%a7-X<2WxDubrb% ze&z4at_RGip>YRpjPRzsOc~@RIez^Z*!o%ccqTr!I8Of-;V#(I(?hN#ch$m$0agna zitVT|zK|rXcx-Sm=GAuOCo3gdBh+DZD%OG+JJf@;gI8OdbCG$`7MMgY^E;-8g;MHnDeTO7mO5uU=cjN-=Ftk z=u!rq=`c*#zKL_AZIj7ydWdvHL?Y+Cx=Fe@;M`kvGp+@NOfynMIuwTU4PJz~69lqq z!jq}#UHLT~K1bJXB8UCQd+V!{6a6_)=-6GVsdwo3jG)+bB||aQhNCxA8}7-+a_Ssd zZpPz0-pgu1oT*?RnKu=D9Qe**@FVAd|C&~-1^Bm|n+o@#z7htq&D+G&DNL}dmV?RB zb6|4vBfmw?r_Wo3FM_yIY6mzTrc$CG}LOfLSBSH!?#wLz@e42Qice^0q=|*3TqjN zWN8plSYUM)jSMzhjd(DMms*1@FTJ?6_T9p`RUh;sBcU_GZnaNO&{|`&T>g6TKpYJhOu_G(a zTy$n_c+ouX%$z|_!Zij`n5{a2)on`%%oJ7@G%#u{YRhbfihk_J9h8Qx(*hy$Bs_va zLiKls)GfamHwlu;kbxpI)T_m$+0x7QTqtvKq}S*fiU=rGqgCam$0i*k!D>r2Z0Syf zLBvX`dqLvGIu&dljSS8=Tg7`rV+Dd*U==ckiwxbB1z1rdgU2d87Wu6d9W#AS$r&nU z>P8l?ZAM=XgzUhP=+Wq%n{O?(8X9v+VM=P$1a9`YloX-#l-(s;P;j#$rR;kRSfqz- z%|W(Ep_*;}%O<9*h}lGHuIdWe@4DW!oe?G+CC6;@pIwUNTM8R!lByJ?CT(pQCE9v5 zzm1Vr4V%^?gDUfCOSQpP#OuD=%oa4I_wo>i!W|2MC~SrrI0UrZqh=ymiYM@h3YxIdlBT#MA-iE(=$IHhBufsMbZ1J0zY|EN06KeszH@`;7*h z($QCAJdw@rmg}2aZ>mD`2Jry0{tzk!^^XD}7U_0QYR>VJma$n&)iB9hr9J z0UKd%kVxGF+Rf?^cQSXm9VcF*u*?Iwi@C^>iD8pPZj`y%_yO50yP3Ou4k(o}bK^#S zOabenyDa2Ng}F;%lmyg z=tprfQL9Dlq=cZWo87Z@%hoO3+Xwk29XZDf1`dRUX)AmT;jb{R8nI{Vma~jEV&2*I zW3n5BWP;O)CYf$}Gh9Mz>tVDE*Fq40x)?A0I*Cu!byY7&i6uV)3EZt)&JqE(Ne=}` zTvdd?g^dQUCaek9F@VLgE8ec>v?W0(3ds($QNKPqMYOT(^c;1vzMvZLQ+&wCy#Br7e>9$@ZWeG~WZ zgIw=FRdCs?^daI zZodLJQLCXVWs7)By$3?6-b_M5TxO87^BRY@?BQ->+d>TEd+V07uyeQvPJ7K(gERwn z#|b8U6k;F(hJ*ewr?syul=d}Is|_vHVn6U~&Fi;UPLt*}_O{ccd0h<6Yb0Ou+G0RJ z>-x-(MC&@2MunSmp+o(!)F}9F7aKfCyi(N8&gVnS4Ht9X4>NaZQR*n$Qi>Vo+RVkg zz&4vFPZ>*RI;R4a&fZOfO6TgTLZ!3i>rm-D`ASqe&)T)9Ou2KYQJLIp(4#UX)~rZn z%KiVE)PIyFrRBd-fPQp})RRJ$f zD|MhUX3hHy>bau*lTCL@lYA(H_mfVu^1E{Z;rirLuC@cEo5MH}HY1^&CLx2KA$2@b z*Iw%=`_|P;!^)g?u+^+zt_n5l&X)@{Ycrj2$XBznrzSXjIiXLQB|se~ET9TrMyD%C zLeL3|Lt7M9&sJFF9(k~FTYlj4r21U~oE&(JeZ(AafyM1u|7KxVzNlHSU!;Rl?pgl%I!n`>}%;Jt0wFtBuUMR68~O+Fa# z<-vN`sPTv_akTPpGzd5GI%dg&m#~2I8os+Y*SUmYbtDUeVFY-mJ z7dS(pCf4%eSlAGgkhQToWQ<82G~mkzsr{?~BZ5fV#+Lc^MgyfqUl^Dni#T>88IPhc zVoe^yZX>DG^j4S``RGim3d%VZ&s*Rn!31{ggn2ARj3pf55v#x&3k6LBzASr!2IByO z<$j4XKT)XqC0=4K^(KxH47zNNSHmWct(P#)pv}t*euJ~VzLR4uzq-f@ruBU%#~M7a z-psNhtMt$I!>Tl>%}RiRXDsGm3Prn4c;&7T1uAC^t-BG!ONbbAeBKYpjCGzQ8Pqgc z14(jPK+Efjv4Vn<$`|pZ9obAEfmodd_9XLy>7uo^48w#YsHLcO9jlO;k})Hoazz-iUsmVfHLYqW-NW6w1zM%^HElk8mQo{g zPMX?E#REm`g#Q7Z1 zIvTM}95Pm|$)z{VDsUHF1HlgsA3r>EVBfx(nhj2^+pf_v!rOc9JyoUVXN(6`%GVZXkD4H`2fv7wkI6;uq( zZL2ez&fC$7Z8Y2!C>y~YPj&?Fe3BsO!+9;>aO}tsb8=?-km&9^pQPPwVL0?8A!mk$ zGl>_~ecq@ELV{DJOf62dlZ6mI<;6o!667%u{T6(F;iAX9Mk8D<3JOe#Djz!;C&vCSIT9bEOy+GE8yZV`1nv6i&^-?%Tzr_t;xflE%C^&uTXi& z5@18}L!pg0JXN*!J!$zssIAsYiT=ZuuxYF)WqTCJY_xv0VTM?8QV56nc(vH#&y9d%a-91p^o@)(BJMzbXnC{sZHz-r#rAo&W zetH#Kulv9|UqSlZvz2i$695PH!HZ=%=x{IGAf`=qAO?Zg3@fefpuY+?+V1-L+=9~c z&im8{tGH|-j1x5&v?kXT>;J?fDr`t2OGD$_$XX{-(&rFBIs5F-InIUT()Z9%<_L#8 zBVrB$Np!)cqovU&JGzRxa#a10(ak+?vN{7F8qN?{oJ{GU@9q-)_vA-dQMj^Wcd1et zQvb+^w5qV^I4xuyosmqoyHcv`9x7EvcbA4p>d}dM;dh)7Yjj{yIUMia_ZnKRzN_&X z5^vW)y!~nZa#f1AA&9qUY}^Lhms(&hjN4SJaO6VY{rIUs^BuVMWzDvIv2c5>;l_rfLNbrV9S?z zkm1nl&GSLwf_!fH#}?;Lv}!ZL>gQrJsO|^6Ml+hUGKt#QNkyB^DoB%nwIfD1dr`EX!u(E>``ekbv^JHb z&L+CC&}rSVGwvc^amQSD4|B<8OTW+Vk;S2&^c7OYi+f#*I&Oa+x8$%nadCz~UBF8= z%m>}cC1MbfL2Y~_msFPZuFpMyJuSB%Jg|+O97{qkio6wOXfiHn0`rfe34WhtXQ>fZ z8P~;|E;J?zZr#$QjWxbxnt8^>H4*`DpvIVjR=Rr#K_giDvYlXx=g66ER8ofY@f1yj zt+M~@)-9<)kg9Qyv>X1#l}e|)OzD&pQ^gpu)@-Hn_5bD7Bz@oapfDC*3+a1NzVzLs z06_dES8kI+^ymx|A>4$8XAIHTs2;V0yf196M7RTu^;P@XP`Nx(94Zg(WEA&^iNHrU zQuw1%)ZQx`2vHWxK|kWLu4e#Cv)B)V@m(dcldZFe(Ah;8{sx2*5R=2UZE$NK!@So} zqA4DeK8gt3CXepmmDmSkwDowBDWM=T3|gx^vQ5eWZe+5Wg;BlCl+ApbGS3ToP?nQy z?A~yW_NoMPDsdoeo5nUKHjQB3i^901h%!j>IExeX`3_{l<$y;i^u+Wu-gi>$tVpXO zxs=oTR@w@%%q`-$4J2GOYOuaS2XZA9xQ-fCVs0slt8PCF+exdPjMEmfl8S7$xYvbe zH2LptJBuC##S!~axC-#7=?7i|wC~z9#Y?hXB8DGr#~_~6`8P^iPgCSowNP``(wZEU zX@w}TI?2Y8uo^Y$?4)oJw>Uv$VY6)3rlk>2R@MyDXbCn=yY9yq{8(gWb*~WvgwcjN zdM>}+V5_ZLXzxu*M^ioRcgVNd8bz9%(Xw^f1t%Jf{b7)Tg|+a$u-Oa)Veh2?0na}G zRJ0=m@*MOV+~g=e|9~>SWpV}cJfaOs=JLvpdcEq^M&`=pp^;s~m2!D!)$?`?dzGPz zH#Afm<-2#4%k>@gx!u+J=*UpLJml>vk9yunZDi-poq`-G_%kw)AS8mlS)q=XLc^jV z&BQ)>Z(m;@nUYn(;$C;I?KcuXC?-)mPKsVoT?ix0n&Zr+SG?x3`|oF`%(fF_=Kw|8)~@Kw_x(UtlY08Bkj;Z zLvtr-uLnw$1s+~DVjviGug^Udoaz)r>AYv!pNW>+u`_k-BICS{r zx!sH{?+AObbhL6MY)5t<#Jyr5G6ubdP!n6AvZ>;&=)`FrcsNXJ!mWxJtOMk#Nhexl zmzp6J2KA$j8jb5dSBGg8<%;N2GxJsvV}Zt34FQH{yCl+CI3&u+h|tc=-jK~=rnC__ zX`f%Cf>I>80&129+R4km?;?gF-kDO4~R$^0JF#fS}PVl_r%WULG{Vk@8}&Pzy=s!JAbFXSPO$9A8wzkfDp$uH zf~PB>aRuXoF;dNyD9JWo2ucc)CY*&+K7&fLkd%nJ*ClJ9;i?NDLw*)wgR1y!`|4WoOLo9QN$wlr(eZ0qNk;PL4zb1RgDUjqwVu63MWz>Ivf5&b~Mt zdUQHk+9}%s9VOGufHm@8&lGeVSE>T!;wc2ZnGe!KO)$uCIo^}$;d81JM1a{n zQnwvR0g#u0bcb=uy<0SnrjJulobraSoe6jB8M$FMldMOoodS&ER)vZgc{Wh@{KngG zIqovxQby+tkGQ9T$?Z#=)xv-?j{7~xlXHMZT@Ws_$?Z*+_z|xmAOZepa1V$2ORT^D zRB)UebahOTKsqeW@kY3eBj7lnfancT(`%H(>1Q||Z0oyG)5Z`6l zzlw>$UXEp4^KunRw>0N14$`H3ch7l?cSo^zW2IagrvFDPrB-_mhXAy1@Hw)=f-G*w zOMwI!qUX-56g~C%p^W}y)AaZiV!!H*I|NOi51JNjiz#lJ5bB#)*MPd&cQB#8{mN~< zQCx*SN~Ta4m4wOu=#1okGN#(FkVgny#pq*7RTP!UROIWhyY5<>-SrL;sbh@o4+Dhp zX;&8nSK>fVZ`R0!YNsiXfs)bN7-OdfA*tm##2OBWkj+eLwI`wm*#gB)BFYF0cWYuo zAm0q*1a7}_Lkh0u^4^ijz)$2I8ChHeW#D7D3O6bSHkoJI^}2tWksql_rSqOM?Ph#C zc>}45%G4-|OY8o=>B9$A77amY)bV5>Yf>4|y!~_nLfB2m3{VQ0Akt`NWZM)`vxP`r z%IoH;id*zHhJkZbUj0$rYu2l@IPLF5rxDH*6COoO1-PF3VGy%E+@mnS=sE;(FD_>q+2w9O%G>MZSf({H3 z2f0^ceafdeimN5Q97fGjjZ-kN!TkqrI&rA9kTe_HsAy3X?MH=bj%bAQ*q@^rA_-f5 zH69mp=76Y8G;F-dn_;w)GMlPEQzu&Ukyqm>K5C11`mRv&Zx$P9At|1!-}i?ITgKcw zj!xftX!_`hV-P^5i|O{ALn3(o@en&#wa{#TxOs(2lW*i9^G8*D4G3+oy-7cD4>p%%m37DP&i&45?i&-BylVO>ShmI`b_iG?U`r!h2L4o*%xCh(Ru=os zb|diuP9c^`-3S#Qm$j3MYmo>VZg8vR7HELG8+cCPyu!Y02ztk?Z2rxFJ65kw)Dyast9 zWQAxKi3)+P>JL;WkUbvG&*K;<)SM*54T^L?GG1xUg$)FQOLK-rOS{VW4nJ9#k!9o} z!n8(gEbR*$VRV$Xrc@S#|9+nEYBJeEn3ny#?zJ03CvSxgmsSiw%&(_dnA?l_cT`3wpO zZ?@$54dNAwVMW)+#S(QKKZ1>RP#jSbHLyMrJ1J)O)WfLC1u^cS5uSc#c#_To&IDKC z+iNU)E9wZes&4>#f1o@t&taR}BF2* zfw`S)7Ra7#i5VW$Zt?>}`pQTTQ7zIBoTdXwUDIv7ynC)3Uf|91s7qzYGUWxS)*N5pY=67f4L?es)idv)sp`6ETTXu06a>W?LL6y2cPd73)ycL(t4q)H? zf?z)2-jxgV)TvT!u;j8?vFOg(yo4{1-mZc9H)pR#TpW7*kf`EzFNz7-^DZfNLT8nY za~or0VIa=l9*81njH2-wgy1G57dk@6#g??(-&54Gt+-u`z~pHpXfAqG8^zO`&9c`h zprer3r2LDGWmfn62Ct0?r-K6#nS{5IQI7nY2oDNp=$;B{e2M1aaaNE&!CxJDrrRQp zgvciULe8A-T8-wypXdSiuCy&lT3V)0961%;a4N83Vs?-plwFnhlHC>c<)10yPqza( zK!`>i2zR0DvR_LUSksFZdBje+7Sj1N7j{sg;l}C7ff08HgxsPtZUTtz&inG^}p)iozGj z7wAq=p%yuMNY(w*k{W(+ZXx)9d#$SkS7v}<&!wBQpQ*(5_0w*nl$FEw})2(Ye@W47#3m3?LbaR5{h9QBr!S!ER24g4BkqN5$ObEVHG*oP|^9pNDF zG`l7xqjed}eV9b z@#I*0Zc?DDsCI}a6ZTP(45)0H!9eo9-B&fP6cA`G*&#MPH_exPxZPWIpvc?|k9@Cj zq>TV`*|ghvGy#K63K~Mz`@y{A7C9iSlIir$1XCi_o}1c!qlR9!=ZEQ|*t$_TD6-iH zk}UZ0gt_Pz!_1}@F>R!MRBTaX`aSjfXrtCa(qlMkb}L`G9if+Ik}$G))Uu;k=pEvT zNa&#Tfw=0m_`xum=JN+mTSYMQlBa_8ZeN3Y0oHs7ER}sP=T}9jeG6XXRTCaf^H#&F z+BoW@sdgjrTMZl213vbSj@q>zB-6lQpWMI|c-^9*GQdrMi!6)|MI7v|a!=NeFYw@i z@N!o#rzY;SvP@0FKToCI+-`aSra0IO1!$8v86Rvn8Y}xm$N-L$fvVhOy#L4yj_x(E zU7t!Isj(7Nb6--#$21_7f11ZUIg+GDFGhQpnvm2LKO`!^79vxN`+b|_)6MMP=yj_A z{yfBOF@GZPPY>-6?Ll!OY8(ivLLw*v5q4pe0VhVs;jn7Y3^1XoeIl!B+lmiGgf|vDI2DU0R>JQ|_ zJe|>0$e6S#e_li;vr0-Sc05e;{IodkR8uOwRe~b)AI3#GAiPa2N`b9oVx9-dOk#6^ zWwjzPh_PS+wUYOT%K@w(`Kh3l^nX1k5C z^~&{wAJgGU915I6thfTjvM?TL)|_l!W)&5al9>}2D<}YRd%94@IfR0&R-Qc&fAu3q zv2kw~flA~AVl9I^&-tmHAmw3BOPEag-f>n)p{-UlSb}E{X{r@Ux+)4sAvc}I)4ka&QF6vk*t5P0SZtg>B1tX(iw^y#HQy3+>5 z;k-2*J;oV35wa0ysl@>v@&H`5Q*)_x%0f)CxW-gAhj>)KL@osDlPedBR;ae<)LNEW zY>zKtjA812oSY28NG*c!bwM-*P~vL8v(c4zfNnc_U5LjBiyusn4t z`aF&`3)Vcp!{0zlM7%l&9%q17T7tTJSVpFjMdX4&%30gpV@n~rBNcJ5i*gjW{TE(? z6iucgEgteM1u##ZUsF=+8+Q*onVu15FBqi3*%HwW4-O0+lu=`!$qXlhUL9{39UHxX}SmItPznhVu;HfYS*G%s_E;(=ANd z39?BUQ$aRa4%>sv9n_hglg@Y|jmTsXPi~xa6qDAv^m}0vkacw=$>G;6*)k@ikVxyV zR>RW93^_v5wWhP=rsb9cKUp>pt5VBWr1?oqB5Dg<3l$mbANEe6Y$^3xg|0DKZTX|} zVno<@u)cySD9=3C=-8D~vZz41!Ln`Xl17jUGNYb!F?OCv5;p!TxQtN<>88t7>~ zq^;DvNjN9Ci+#vOM>$qKNpc8%VPYl~_qwozD@C5Fm;G)=dq)x6aR_sv>UkioOWA^; zqhw45#bQ7fMXR`&|HJ+j-=@KpB* z7D(~3 z$Nag5UlrcDJccp`8Y`&Ayrz2GPE{L*>6f+z*+5F!rmYDOS5JuYYn?om#FmlW3^#So zoigi8&}@+m2%0V0bWE8%)@~!AwnM&7iyJeb?3#8l7dI$jt98sZ9+bkb1%4qV753vK zD;Of_U=)1?pjq7Of(|g%y8SY!hbqT9Duja}vW~f3ikILgLx9#=do>IaubQl(@_izw zUAJ90r)tLBo4u%pDPt^45u1*X8MNIzMoWKt*yNKlTNpEkE~~baDRRZRs-^LU{!^QG zR7}Tf$?rO3HiNIT*IZ%3NaaH33KE&FVXMMV&F3QAi$Sb|H9$jALK7l0S*ZF2CJI!3 z3;POEsV(kxg9d!$*T5h^K^6m(xKxfvkq6EYME+9N`3_de9XtlVA1-bdWF^bAbqI;07Tb zuBH2)HODh%%5`EuhV$-lHI%HRL^JhHNvf4OxaCNa43}m!X-gk>twZ4&8UpQqY5?Xn@1RnSJJjD!^;!3$_;pGufsE-vAdg|j>A^q(BP;yifZ``EXe55# z6#2YP5kPVUPPV+9>0M^I@2O?nEDXLvKawFyBzG0;%|NAr#geheqgg8IG=Ju2hB+46 z7-rbKUF!}V%-RAMyEM4Q>LeSBf?AwJtigl%WMTXyE2xY}Ov0eu#4U2OY^cm;$!~Ss zow#Y={sRXO-8^~At%s+M96fg1^vv-Sx8HH+^Izc2RcpLHzu@1y*k}e}>%J&X+Dpr) zS6*1I3=QuX*|}?Uw}@UO=pqeKmRlXR=FleVm1&C5dZe!$p$F7~UP`O7_I-sKBFHa2 zXt5uxerK(1O1UMKmo#eaqz9KjTtA<6gu6GKv)z=1$F7NmM95Q%03f$Cd7&az+Au8h zpyHT5q!;(PEe|&i5a*9G*GK$RSo_WmKNYR1abdIy|!2ePtrlgdM5SiYYpcd+ouCAe32nq=1+z1hY)i zg@<%;p;n|1V@_s$Wp0ept90&T z5ywgIPL9?&$SVgDY%CExKV-N?t_7%3R)dC34oPj@BFjStlZ)z1Nal__3<_CaL4d!O z4N3V+QPBz#@e*^3dxhRch>D#qF@6Mg$5&eXC<0F^jxLCfNi8l8^8o0`fOB~{Bmps_ z*#s3#$_la;iL8W8+k-L%aRm{tH)ROXL;P00G9U=;2jjAO(^t}vP*Cd`^`mp1pqVC( zAi^ZG!mWHolM+{R>8Z@9ID!CKrWaVLUbv2WK@eH)rDY5!nKs8slxp$$G^LZ+4UYK^ zouvq^P*J;#x|dI~F$xqYiP`6#0wN;5mK(G?4N_8IP`qr58RZbnz;RU|JUmKxN&Dw2 zD2O#4T{-syp#V4-97=3!93(2KUchCQN@uipcFvcRvTnuFeq`njrI2SlE=1kffXTR5NpA! ztsvF7`hg!OJR(;( zBg3t2F)e3Pu@!J;y6IJycu)(Ym?A6SD2!&YLbqyI0r-Q%U?oe>m}IiR)rp>kmn#gQ z#)z-D*pBL_n@X2`iSv}xJ6s)W74?zglIAaC09+OkRD|P@a;}1#h&(<~OT{A;r;C)+ z2p$<~%CZM)Ru@wKcA^wm(2lJGic#!X5Er2|CHH|wWj2bl3?f{{YLS|$e#Ld79_ort zgJ<>}7ge4@Ncgc>u@`fKOrMAv8m#~Ul~e#}suho+tBBu0hE<$aXnIv9ct&ymVh}FV z5mW@8p7UaEs49*xS-?`AbdXMX!8l7%X$@ri(3kE6NglTyhzbP~f@Kk@$=)(1*KIxO z%%I5kx+m&OEyB)WdEVPuQX@+^GU*XU6(hVsijO1%fkO&*1;+6oF7ci2W!_v>-E&Z( ziyDTkyTQ^247#9cxK>-<9s}0L9n>;3C#nfbM23)@6SGnvC z!QeuSYCg&Lw=!hNj1~l$DIzLvSQ~fgl8%WVE3!F?;*$2g=4RKl@yf@cExzW!4aL!P}3F? z=i;uq3g7YnYWB*%J;hMu!uabPw9yQvm_uk`X1L|fk<^Yx+82RGT8L(?w#g=-T zDWj(~^Qz1$BT6|;t4%tO(wqnZ%ea(Lhp=!EDO#7q?U&=T`Wd~ zMnx7KwK$aNGcB)54%}Ky%T*2qA2YK<$Lf$6UCj*2awJ}gr9YOv&`?zxv`czd*{K$2 zq6q>8WbLSgv}{$*TGc5{7u1n9e$Y+yre3BYwZz;p$r;2C*^+$hAf*zglIssX@C^TiUS+QW0(9;|xvZUC__D0F@(@Y}GdujDr z_C(^*K}TA-orGs_#AeCUOR(0g>;jSdKu{BWMTr@{I?`^6L}I!fs`Erijk3~q#k%E4 zyJ@+k64?O8ExV${qHx4xa~KmC_Q3@>O0GlsekNhfB+=}wZ3Glm0OxESlE%s<1|R{7 z9HXOTR&}G^)}(gJ)h!_dsFE^PS1WjwrEF!gw$k%DPpMEHJ%@NaezIcGJR=L}*lAi? zWTe3qk7I8>B`PwAq^I9D_OeL#9E?$a`5@7>v3DB2waRnp;bevc6N z8fRA~N_mlP5bQ9bMdWiYxHH8Gusy*Nnr1jdl03SnR#$n}3B#~rRA947UNvKEx|xA| zBE|{IZbMnwbj`KOYDK@wkd%d#a7pE)=^}doRH``=6?+sHarNen!$vLr3>CiLYv*@{UshK_{R2cj5@X$0(Yq^gI4VmODp?f z+%&Z2dxjJjrY|a5WAXf3hNRM!;lOj=F=Pg`x?f0-c|&FCG$-w5cE@I_v#!@cgcNg? zQM#J(^z9;s0VwPbajhjFL~u|G#CAC~X<1Za?sf{8rH@P*OO?ddwn!?8BR0>aJj<9N z)m&({R6CgZ!rHz!eW_4h+eJuo#N`qVr8~abL4tPLVp`mxc}~id*vvxMZqyI}I$X3U zV{L|#NX-tR+dVpUX^nT<^i6HbuF}myOv^JPg12w?8pXY?w@6#SnA6A+B|pu68&ioC zYg*E!dq<$$xD7~FopV)+R-Pu~xXq(|N5pK}5ndpLmrr@IH&oo~?mMD=P;EO-K2KK{ z5Y`w69rL*vVe5lx*laa;!UtH>k0~Or$gEKW!`M6OF-BMq@+sa zog6o1aut_p6-L11OUDBc7U(4eA0qO8d3B z+eH+%~5!MWPHX za8;=|bmPAe!H&o8jl+QTokLizjEtR8zi_>FvobwetAE+1}l5RQ`O9Aby}(gq`c&NKKT~osns3r%$Zr z(TD`)nv@TF=%g1w9UYR=vAW$<_&}d~S5~mOcb_a5ch6o2dx%`kbnOmnW?S3bz~TgP zW!r&Pt4(ioj!vOHs=FOgnRGm~<|KQ8fKwFbZj#mkSW2r=Q*%~wky9eoZBbtmMj*Hb z{X+xK=pR#Ff{=CEnN1r$lu<*?l_}LAJ^4#b2GoJEp$l#LEbPY%qTVn{UsPAbu@@%y z@EDUsAVHW?x)ITJ&1cBKk@DV8?IDyJH=V(vjG~;?<5LAi+vI_K8P&9V(VQiKvRA6QR0C~eIK39@l zD@#i4T|IEOie8;-FEA}IOZZG2CyhK%@NK_l(nS2Oce)Vai|WH zv7~4A)UOcHns*AB!JXR5KrU^K(HZSXJ}Flyi3Xfnx-1D7cy%#uH{%lYanhi&@kBy=Jx+ z59hypUW?C_RwQj*-(vTavVgGjGHMjXau+;D{72ob6hbp74VQFA_wN#b-Hy1fSwldS zmZ|hOwj-nq*2|OmL2laM0>kev=5JDN0k}oX(e-td()ju%+zlrRC+R0c_nS&?^|p~;t=pS zD`Tfpt|l@$+fkz!)1{BZp)#)}rRX`y#;RekgoRHMc|nXjZpNFn5oo~+T%ICoK&!Sn zL&yVyi`9#6Teh!kKD2s^ND;T2WN2SQkBM~;j|UjB1}>SkZ2ClQVbn_Xo7HpaF3hKw zrPffx_NI5ks1{*h$XBowg=9yi!MSwjC*)mT{VH)I#NKWIc0Zs902Uwv7bOFx#3JU9zI*2JGqZZPLAx|P)<6;lC zE_Bywh0ULe7FGrQwA-_)%Asj7&0}1__XB7a?1!scXst*IH-VuExCtGijsq_XTpbTJ zGETa4=qXpMSxH!EI55CsI9W9*$9Z$tjbzuZT_Mgb&=7*6XZJ`-Ea@KKZl7o{2n+K7 zR3mJ1QV+`&jIg|kD5Gpgc}K^5ntNUaj~-fzggJ5&R7@`ta^QF2LyGW^R@d6i=1K`? zA4A+9B_je*5Rw}*(lDcTNz0|g%%aEI8>J_&RVTe4>C8nYk_OHVD&#sXY3k`h+lg8Y zPBaT#u~gFw+Bi;i1Djd&TPoPCV2vCDMYKa>)&cmQO(d)Y1d4 z`a5I*hI0&i(~gvyemD#lW7hB&xn;A^DmQKlvSuJL0m)svB?NhAeabN*Uf^?HfH20} z3-b5&ex|f#vu{AH5jvEy8{?6CIFwGt)eiGh7X?^rz`_)Qs}Z09z#?a}OP_mcXjrX6 z<%k+%nHeKJI&6r!cg&p? z$HMhKh3Ujubz78@T=FrTYzd_Ur*U~E93Z5<8isaz`c5}Ytb{Z_lUGeThi(&PN((T0 z$h_07%ny+UTFR}~d_)dcE$_oP?S@zh9KUwjz+ZHZ^MHAnz|y0*8#{HGHe}D9N9C)D zO?qVvl4R$*z$r8 z2^W*=Ws@gtZUvXb!|W9&UPGvir7lt`xASzrWqN1-6o}NhPqK!-u`JQ5d-RZ!wM+@; zy8Tlr8?yk6J^ zkA-zX{~mzr6k%&v&ssVd`bvd@)LLEIK8|Lj?hlW>_J4 z%6jlnDtq|Mg5D{%{rNq%DT_FnM zmf`!GVXc3#ls?#mNBRa>n{X-fqa4(!%^G?~AEL>rExb-cvKiuLD^nB!8_8{IbsR*n zH~dcP>c%OfALZNq(#*on;67sAesK}(9z<0(FF_Op=%PpPoQOGLP))fPf;el#RS!3^ z)M3vmORR3YqM&%wrSxN>ALXA5?Y0jeu=nKr$o2O2%j0?;|{U|!*vu{UCO zZZ$3-sz6c;k&k|i+JR+5l-*&D?Vk^{nC@G%=Ad2^RzM7)6fI3}>E6htsO7VyHrTBJ zAX$Xsg2AE5Kve-H?JY~aS~peNF!kHwUNh-Wst|YLNp0%kQH@ezDm4&k8R-loCLTjt zYawY0<6=9S#6_=(0XIp*Z*|9I!YR+hfk$^R`0W<%b(9K0QA}#ZaEV6^Z)E`X z?SMtRh>2WCe3`|l2c}mv&!oc2rcQ*Lp-syaBU$9^k}IvCh~`o}uO5*0RB$Sg0LQHD zjsF<2Cn`$GJX!Z@67K@ql<7-)5EO$h?#x{5$=p^uUTFD&%jlAJ>~9LJ>|vSHb*^j< zX;LH_<+#q4R^!4BDstYPbc8R*#Dzj2i(A!$%mET@Mkbf{XY0^?^ z%YoB=ax@V4|FVMh7mPR1AXDe)I~+yz1gMl8+;Ns0$V941S>I7*sS@iV%gZixMqQXS zloxWJi+fCqbdl*8oAMW2gNRD zA6(MnvB5#FiP(juC9f97rKml)hc!Jv7#!YF**!SSd1d#m(Q-eHH**G%Z1zfBkj)ms z9?5`gf(VImD@Uu$c+5)@E`md6g3V?W1Z|2IpbM&?itp*e=LJ|OTAmakhAqWIRw?%y zGGQq*@aaAR5&RdUup2T2s{J#2q7XX^ zYhHtoE1wme4DS>g77BxtU^LTb*~_8x`;W9a6_i_m6I>0K3h9GR$=bnQj)h!b?EC>D zqx!mwQ-_WpJ0L?|idv3^%d8@*1mAVuhRhz$}9l)9H+E$r3_pT9b_-1QZ>q&RH4>q&-mLEGuR+=zzw0 z<&7tUk8CmZTuRuR11Y&;%PeB_Ss^9NDUf~6u@GX0j!{@lM-7lraIyt;h`tm9+Um*< zQA0a$KX4p;%W^jb=TQmHS zE6C(oC2^4f1Rwc>OF>}5C#A$D+cC6z$L^iGhIWsD`nC|B_JUg2+|L_c$KfViaG!=l z%q%(RMBpbPH64F17isx2(^3IWrcF)UDgGAY9(9{emyIT~x)6fmeo&kvb_7w;=!txqw6{s~Xyv4D_GAo1;9`PqaSj8EY<3L>XTKr%bP4oE! zr%kVkVJe1H&M3BRQfeaYXy~dZ!9)dMM(lFjRXRC)s?gVe|FzfMaOUi(Q%be5Y%l)- zf=+ms*flUZP${b$L=~v1DNG(J zWTB|GuRtJ*dx!eX@8SMTHB^wQA?0&wN~aSG2v84DXym~X{>N?fnrFpB4Bdh6u7OHr zpfWH#uw!7S#upD|7xnhZK#cC`(_X;myr>mhf@nJR zdf;`eFxAg0Y*>+thP&>Mm6es1Zuph0?x2BvY3oIY_%#Xm0T>GlyzC>val~~h2(%XkvXSfVb0DU*G}uPRE7llvZ2%) zlDM*6*Ro+Vpi|QNS^ElRm8QCb&aL4k&46+M=5(e~Gi3P`38tI-eM=da?CM7ZQjf5X_5;)* zo{lt`(h-aXU~L{57kWS9RRrf5!!B$=)+ae$;~>uK5!&b_l}!yT64U#A%9bK-Zr!C) zNjhZJLM~jg_-Q{TuW`L_!EljF84G%Gue^zfqKqok7>lN?MBA z9b+04?Ee}E!4iV2QroR!ysI+=66C6z{>@MvSXd1kvC(C1vF2lvmM6x%C8Ok={|Nd4 zIS8?Q1oNl?km4T6>JYWEqE69FJ*+bRFc}Csa06>n7ZD7ePWyO)Va8w(7AS09uR4&Jb#HIo@m?q@b%cKVGzF)VL8Q z;|T%7PQCmor8=>bWx6{kW|T@w*_N3EWSSgAW!kL}lMqB)s+7G?t~VWN`&A(0Ev9L}g5eQkErDF1O z2~T0qW?lBi1&RnGkxym!G zi`IlcZmlT;oM{w$DXII2Y38m1$vWBbbYdng6|pxVDU@e~X>++oeXH z+z)`{DKi)t$5kiWRmhDD3tenraS!9T&(Sh z3Q}qxhg2>bx{)oqrv-9?ePnQCAS!O~)_cdY2`OM$ghEBn?zu=@j)fFuMi_N-%PVGv zi0m}q>Ww5>wv63A%)=#(28f|%1cD;7W{YB@G8XsL${nCq!>bB{&-Noby_Ti*9yG?9 zqLaM^Bl4kQqnM|ZpezH>fX?ZDspw?+hv=d@Lr8-Mm^(NqMIW_PyteQ8QOqY&ke#`M zE}OL$Sehpaa*Z zh)r`x)aJAVpcI^Sp;dNDLsNZS7|K*ToT^h9tW1rv9}P012Nfb>EMZX(Ogfz?GIsJp z1;eV`j}ow>2|mmR24kCI3n|Gvq3vbm*oL-^CAfrPIgA!#@`nUDxEH`xw~c5c4L{+L z*I;3wg1U<GV|!F&>eBWrA64-Qd7WdE# zo>4)YR1hc;vuP|*ArWg3ZN0U#liEx*f76m##b~|%nXrgEU;-a)p z5MY2jEYhAny2k%g+qZznQ5*^PT7F12e((y9kT6;=M#38HLvITi>t$?g*&-Bc$Y+<VLr0yXV;N+2vVAjSdX@@fF1nY{wW79!uxy+&F37?}?Qr6Sj!XseXDu`<7s$M0f# zbYO&Mo@(ORV3kh>y$UKYkLQgbsa)~}SR`PN>2!8wI^7CiO-)MCDkv9bG*`LMRxeDaTbm*M!m9U>eEnCj+HEq~t$hzi>>>)= zw(xGf6`mnGtn^Z$5EH=%4S~T7;%9p(*WYehiaMs`wK(-8#$7zSEvjW@elI3;^_#LD zA|Ey-u&{`Gk{NfL`0@=LkycAhD$p2DKxFwoIO)bmrK0>+Q&fu5>$CJYRy?s~`v%|p z@l>fvaV7AVb|uHsRB)>Hu16_F-JNWn;g+qBI0&gPF`sLS9{<8Mn^ZGVgb@l*BTR_^ zfw)*=tURM<1LbrKl`ADClIT7`k5O0_Qyf_uW98Z!6$k*{5jqgyw#3t$Xcl;MMO(aA zn7BM%4}y4)6y2@aX0%s|BIm;oV1D?v)o5VLH@n_q>!l{>trdR3EoLtQ1eGtmdny5S z16{Ga#elhbv~WKrwmGCY3q}g24e;fSvM|MJAH{2sh1sO?Ryk-aq`h#tI)kgyN+~gs z%Zbi+{II!Pbago1#qT)ly-EZN&HJJrCLB_LLd*Fuv>-q!N*`8?No3p`d5Sy$*oFWe zq#2~{p<3xUR4cZ6$Tqq{ZLk@}CmNM;2P4N!gJg>;xM?EBo14AyB3ceY4$6Z55(oGb z<}iBd95Oab3MUVPP=EAy-cX4eRi9*IsnZi>-w@YQ7#lznkL z(gFyyh?MotTHSVB){74a8`i-H#0CzrG=+KPX@vek$P9?%3&~;Ph+~Gwyrd$L54Tz~ z2PR|N-kLat@SQxTv38@P_8vlSSOcWU>Ca{lAG7`F>?2GLu4^9>v&?7)IG|YJD;EQc z*}=fVbTGE$Q<1HbGZ&RtgEgyJiuGsdBbB)NQP$A;(4+>(CnzNzHdT*~X6HOQ+S0NS6 zhh>WnOE})-Omr~OaBzvqk#-mu3$9^&y4Dnq;?_(Y;~}xu9A3pjox-^;C<;{h)QjHR zwy*~C%!ET3l+}f)=5O)X5?19*#ZXEw4g}QSn!DA09={9Df3j@H#oEBLnxLPHzgJ?H z0m3qi!W#3IYu*+N^w7|3GC4TZDOUtUcif|XvQZ0q0*26_%&82FI z9+_kl1;T7;F1^VhXrNLjlhh!7Sy7I%7_W@2GVu>Qy54X#yP`nMUe2;{Da9|c(bWqw z(20^4p^Y%9g^8HGn#R8Nw*TPe7}P7Oz(Jlu{tLYDx}8tyFyT+1f$k#Vz4?bg3Gm5u z0DQ=NW5?YIMRW+rXR~281A&D$@J{iJ1>t;MjK;yIN1U$=J7ieR2%aaVV(@`V=Y6vqbhb5_A7y40KAZ>1_Z+ecqJf+ z8w+{_O*W&|uqGVx>U0#%Ok#PUavHo%0(JPbY#q zXUS%m;U{L4nOI`Lf0ZZFzMSC+*H&n0Djiw6)Wo#wsFG3CvJ>r#rq?FYJ!{kbUFm*y z$yNgEk7Ac(yaWP8hEwV8wdsKbcUppT8gm?1gfUA|wG0`)W?jH2AHN|!de(&9b>FyyfGpE~{pV!l#?)Qh8E1H%yDTBk9 zP$ZQe@Trj3D3*p(>7M>{k3Xsc^va>_5nC{K_WJk|)`t=H%@W8HPPrw4pMii(}rWYdNaO0ufkYEf)zZMxrQ8CulV zveo6<(*x}u&Oj&$2x(9E_?q2IP0xoYtBW>v(pC~0W z1I%R=OhW{=Ej{2PhzHOJaFtJVN7Wt2v~l_XaR$@fDX(uwwasENP_;*>TGET!q--g+ z3xRdyoT3U)^mn8Od?sgQ;Y%zEJ$9!D`u!eho8!6x?rYd2#gc0p`LfV_Pj>(mOR>j_ znlK81@{XlxYC+B@#iD77cuuAJh0(YkhxQMpdwgm$H?1%W3Iz(ftHD#jl}VYtkt9yB zK@bRF2iV)fgPc&A#@16R)JBxNj<-nh_{ZO|pxnZ<^Lu!Y+r~&)wC>-i2MSeR) zWOO;vE+>)#{rb}b10JqxaD2Ez_fWdqCr+&j$%Nb{^w2#linj1XsnL8-D$4FTi(9rP z77hkhHM*J|WG@u(ql4WLMw0O#??rtEwrWg~!W9bkX~On`X*KNDJKaLEG|;N~ss(^i zbi)fatf3eZuNiKEv9(En8kW`JwdsLwnA1S=;8GfncjGOlH53U4e4JPhf#s8?1y$fZQ4fVopu;vppGXavRKw!M5e^LNA25;Q zXb_%lc5&FiAZ8xL=tSm+ih|neo_MZ3qKJI0wjkGN_rlZT#u~Sx@+SGj7 z%9d5Vr}wQsW6kz-ddK;n+H>LFPjj7}DNf~#Bkhr*rzHB}l=76s5Pqc+^eaifQuM2h zeznuD4*Jzezr0lpKhaZC-88+2e$m!b1N2{m_|--e+h}4NOQZm_4bvjtn#Y=Lr+{_P zIvuo52d&dV>vYm0U9?CSEz(7cbPaow<$vg|Iz=l#H1-@`;E2lMx7LyP)u#)*618Rd zv2?)90rf$alrtbmSV?}mFvD!1m*BCpfbgom;2sJr9AaOHZW-kHfFubj>NT9D!4U|9 zQ8q;xdU$`>6FdwFfh(XF3~;vBKjij65xpja&G09bB9C8;kKu?Hr`Ta!Xm854-#nRZ z%DDhu?+k4kg_u%BdR2?xLT7Me zSezU*4MS65pwm*!VWNmOmx|Fj}*wLnZ)1F-`HnPbUr6imOFkGhEb`=#`i( zju5H@>{SP?$sRz$iRnxlYQZ)QeRtKKR5FMeny3T|;SLfJa&I}@X5n$Suk8hH zyp(C~OcKQJo1>D#96YM@4xm7=)Tk1pFd!9t@Bl$92aI?%>YXmNv6t@nC@H70i3ovY zxmp&DB_s$bX}Fd|DFkL|9(EY6Hf74L_oM=#yp^k{vxB+@3&3a@3-lQ#8y&Mdru>7k zL)4tq_z7BIkl0);9xUprW;oP!Y=^u$TGT39k-i^hYt-e~v(?T-b*Psy!EOK=D^{N9 z?hN`I0CuTh1l(>iMbwITwKW>?)HI|mTL)1M9$dFY0$?NtD_Q_2x;uT82PZrip=`?N zFv-kv7UvlC1e1}6VY<7W#Sn#*A@6k{y4DiUQN zx7J}xpg?#-!&(h$CoB=Ku?A{aUpu8&sRM=JaAK`#1BKYr0w|0G)P{oZ`8h&do~U6) zrRb#Qpb^6?yRvE*xkKS{Y!Qjc-lz`5=!y9`aJ2^IYqZ%TM^hBuqv%6@$}8E-{cps! z85wIePP1w^k1sfvutXm-7}I`eC2lX?K^X^WPT7-Rxo@IZF)^|y+)jam6J%?4W`e(2 zR39c_V)W86zhaLfLC|XG>f#@j2p+`jfkX&J%x30&0|7$W2f`dS?b$BHa>$1}_IfYz)>84ANEYXRQ&b!%AjVtg zf^4^4WFhK3!1=mqRtzUan*sY?^U>-@$#F*bvk^A@WxLqdB=Rtf9T^x7!Gz{&Lu+QW zFswD^9`+Oh??WIT-PFOSiiDH|c%hKJb1o1?s0U#(w~KjPr(906MB@3fZsawThy z8~h;;2#81{663^Xyd=pq4WF84f{Naf=kkQ5a;+gOhNy}))3B=I*o0-F05fRY7!-m- zEk5HB1e(8O<`m3vsci96UjMRV7)oDQj_SL?R8S)pk_0#TgGTC*<&U=V3B|@nn8QBz zZ{W$`3}An3>Btn%n0!rWVS^7!5Jdmg?&4Mg$3hmP<=i z!0C&qzTBYD7FrvIUHZX@Q{yzsHx1RfZz^+KAOrS z&C~fynadwPf6m5FVN~aw(Bb`?d-GKkc-F3OJKxMQCpQsR%hnCoV{vL$KS*&l=%!dj zvE|j#Rz2&z)=~`yqg9x^T*>oD9Wd*8wt*T18Zr&xdeO`{4M--o_X5{leEvzF;BP}Y zV1z0cHGA*SG>8IePw<_mnIC_W_QE!YwZ>nMjE-t<*{U_o!1_#yf}v8F zps#XGWMEc#C&K$*qnhhs3hsQtR$1^2^asKlfp8TVouaxnfAEaIcZvbu03m%bju~_> z!i{|&{w#x;4(z7P4B$*Uu2zbBs6}(Yj6G2|QQn;|$*Y?I!9HU%9>9kM3q-X;s-q^y zNBaJO;q7?HqR=cy)}t@LaSvS&Jxqjh>_+*Vp_6<)eUg&a?Um9@kq;&#!vT6cb{no} z_M|kVOwv86wAQqP{U1KFp#dV$e-+PF(=NzywVJ46ylOU+bmkt}m(0$D>ctCTGova+ zi9ZN2qb;qMmgUb6id!Vu7Hl*Xkp28s8{S;V0tY3*QNzERiaQLUG`k!M$<(E;-&VmV zK!vwCp>&k$Rf`u^@25B~(CG~_XN#s}X_Q4+%OUI}Qx-x+U=8$5ZrrW6iHTHZ#iHT% zFzOD#Anol1T^e+XJ{s^6f>FYn0xAMH*(gP6T$2=Aqm=@yKlqCwbll>F963w_BQqmd zXp@2$U8(TnD*|r&L#WScl>sn%Vjdn0@r%IhlqaiI2Fo^ow+l;%NDh>O3|fT0Q^d0Q zKS8m3pN@gObb+a^g#n7$+bcArF%QqYU0QX4nL)pU9sDhp>%u?kimr?5erbk>(F({}606mbb5V}#Vt-S%}oLZ%wFmk4Pf zy9lX&Z7f3agfuP-SIgB()CiH5FAKg64@}4j&rq=n9$pLp0fnf1;Syz)M8T6Bryz}K zlQfbAwJ*cJC8Z1xK)Je#?qATrplMCodcNRFO=`20N+deuR3g2nk%orsToNEY1QHGhE<}j;`|=3)Cs5NCwh9^Xqa+M-G(0 z^RcKQRV~GV2PzduaxkhAlU0ER*eI(`su`Ie{6(!j3teB}ogyKZUjyTi*0TIjGS%F_ zu*BKeqXp9jZIJ3+G&B*wjQXGO>U|7B4QYkqIXYLkF-9tTt5{O(d>J-^O-^%*WYH(p z0I77&7+I<8Xtuw-0q!f?hR4*wvmvg}LY*odmcut&2yr;n?HzyCxK%S-Qw0q%f(}Yq z&CzUKDS~wZ(U{eWdI;kIp&pyVWWxx&cN3enkUF(b&Wym&mIV zV0v?$f~;jz9UaLY8e5chD&*RZ5_~<^->L>kGdj8svCrc!QXKfrAtG3uQKxKyP}Z`u zMa5d($ZPi5uo)Z~>HyAGO``(mL^$+};%J@il4~o51HQ6-rECYh|5MN=B!9rk=CEZ4 zUZ;S^7&4`72erP2I)ddoo#D<%0xxfuD7yguKyHhC1AN5z#uHgm)0j3X<73XBj?rf^ zOxXP9O!iOunnoxb_6(>7D;X>p!aC73GSsmOwY#bjcrZkp0slObp;A%wBA5Yimj^J1 z+4j)Hp$K6|AMDJ8V??H65A^SVe@EE*7hobGo+Ud3kxs=ho8e|pWm?6d=QtIJ{uxPa zFylZTz~4b`OaV8vT4l}-)MV#v9z4@5=&!D3xK1Ck9@J`)W?(RCsH<%`rSh{%{!3xb zW6KLWl!kGDEm45S=SOT(6s~^oRH}z)*(%0DrsC5W&Re1_bQ{6b5`LP`YBRHAw0RZ` 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 Q(+fZT@ytRp&5oV^8?-e3W&i*H literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302170004-Config.rsc b/MikroMaster/20260302/20260302170004-Config.rsc new file mode 100644 index 0000000..3c5575d --- /dev/null +++ b/MikroMaster/20260302/20260302170004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 17:00:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302172004-Binary.backup b/MikroMaster/20260302/20260302172004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..aa294da906db81f57b9ab113aca57f14cc5ad3c3 GIT binary patch literal 289184 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

  • K@wKIwY}1^T@L%-ob= zM64fR_rmbL6q|BjxnUCy_6cCq4GeK?x*0l|ZMsoI*l{y*I4+282#qB2T`+=e7f`WR z0Mk^RJfXIHDO7wc{|2;!~n8bNKrnqT`h2 z+EI)lMzHH7mZ$uM061mT}(t@Bce;#Je?F+`#H+n?(qoLJ`Lt0y)E0U^1qt3vEHU6POZ%h;5VR(bF z=x9LfNT?|`ee~ts(XJ}|k9`}JxyXceRgw9dwPWT+?VrXR&Kt8*iv|-LlH&xD7(pfeDT zTE};`-6~N(JrV1ImveeoYkPb;cS4~?t9j+|y_ye=z&-*Z202s4`=^zcwzkJBd0Kfk zH)M_}Ljn$QI-7+g)yFCcb7mumW;Qh$7VNf7HlIE5TG7flinSh;WNO;Luq&r z(Pm=-qEvtf6KytpC_@DJE(LpC^(de-;qEF{NcFODw@{&}BYDWn#NHlNfl|Y{b!7@o zEpD!z)Z3$$^!aUp({Br<-(nHOZ0s~~g?fCb2FR3hGN2ES|I{Hu3=Ya-j|1KWAFA&H zMKx~rwnn#-e$P)QLk1H zbGvy?^pN`WmvH&A$5614RQQY(=)goEwBBMr1UaAKJ4ns7Lzr!3_{;|p;Rt#K8zJFR zhW>)%zY+&-!8iFY zg!2Vk=gv!Y9k+5;banmA4J`{A7oBp<@{Ma2uRM0`+~tvlvzl5v7tddCe0Lc$Jf>`Tyw(8m8r&sOSHL5k6+Mu>e|$yDXsC;^@|s3 z@o2I;G_Sq$w8-&?f2v30F=4anlTxU=NUS{^MMJ~EjmE|Y9)1JXJE6H2me=XeUL8g& z0zT(AH;2(<-E8r|GTnHWBf|H)e67dBe9lPRvmaB2*oMo52)zqTaBpL0F?JObW)uo8 z9$dV*6yQ>bOA#&@YRHF+ic1MD76!Yb^N(KbdO#+_&?UWug(Ex}g$(46yli=fR77>mdT z412lXG@n%nKNS#%Dez}Y!L>T64tv4(bTbeZ1S+`szg^+JQj;oMN{#r zSfbq)L!kqP8dn&K95B?n!cgphVTKjMQR#Mo{iP4K!)!1ZG1{qcr^em+@N|H=LLEU& z{LnYkW6U@;nBUMku+CWC1Rmkf7mit@vjhjFn0D#Qc}=loswL2=E#f6Z$M`U)cH^B9 z)f=j3OkTVEn4=dTvwY2p$<-UGt65*csu~`O!N{vjYJo(sqY_ycux-9?`7n}W+AeBF z2oz`XK%e1_k4{5ZNjG zK6K?&1NP{eT3?k$Ntx|wR=l`rMNNHmeRQ&JTwkD=@94Q8&^RRs1y3ytw`ny8_jygX z=&yGRrQ2?JtDrf&`dEF%QKY6%$ngSqs`h=Q$SgGX+xLB?IQ@$5>8&zL zg2rVGVZJgRUV2e4DSfEL+&p_bpxKSsR#ZG6$KIjYc12;?kE!TGq_(TZ2;b zrJ_!DZrqeUc*@LI#O08wecl^vzE^tqr1|VXEB}%OlQ41Uh^3P8SZaEAAQI6+mFw=!GnbSSeKUQ81wGBPN+74Wzm%xFlxR{ZQAMe4`a-); zEhRdql<3@2qVr0L&Mzg!?rgLmhLXny8P1v~2a!ro;9@9tR;$McQ91n#mq&1U7#FKX zWp*Q1h)4vTbRC5tXwpzPp#@zVO^`@K1qXs1u8lP4m{2TLvtfGYx&Txf97RBe{=fn> zKKLHbdbtPtVM#3k#~JfMOy^*)@syfu2wO0MXu3BYA66~EH3EzYu@OTyLxAhNdMYA( z>V^9a0z6ZI8wGfl0M8cS!@TJMeU5PdZ~;C-fR7a5qXc-a0M8TP`2xH^fENnzA^~13 zz)b?YM1YqH@X-RiOn{pOxJ7`M3-Ag7UMaxG2=FQaUM;|D1o&71UMs-I3Gnd(e1ZU< zD8OG5;4cgC{|WF(0^BCR?E>5(z+nMCMS#}{a72JR1vo0eF#(PX@Tmfv5a6T$rv$i5 zfY%Ffw*YSt;Ee)&ngD-AfKM0TGX(gn0=!9pHw*BY0(_PLpDn=W2=KWAe4YTGFTfWF z@Pz_=kpN#Tz+V&KO9c4q0(_~LXfBg{qRWJFV2c1>F2LUq;41|9N&)_+0AD4*R}1h~ z0sfW%Un{`d1o%1u{cfNvJy?+WmC0lr0mZx!I%1o(CVzC(cT z6yUoA_-+BdM}Y4Y;QIvlegXcT0DoVA9}wUl2=EUD_(1`FNPvGNz&{q?p9t_z1^8hB zenfzOCcuvh@M8k}xBx#Pz)uSBQvwWU4$|b|^NavLE5JV&;QuGUzYySG3h;9R{Ja3a zAi%#8;1>n>*8=>K0KY82uL$s~0{j~R{;dH2PJn+ez<&_n*97>F0{prF|4D%VEWm#e z;J*s+-vsy#0sgxHBe$Q?{{Ix{wv)7pEn({_pz6dGmw4MchaGP!`?}U6OI<{@BdCZv~c!2X`AZs zcL@0a*~jyk2WcMJXZ&Lx84lY_}_3Pvg1vPiZ{A z`l|<9;@RiLzk28!9RBrRJ#;CDU;3+u&g1YMfAg?~M11c2o5u_%yz6fsx`w}V_utaL z9sP!fw(|R9-tf@<93K0Ihh^WxXWSbewn&N3_&3tD_Io3ZXa6_SbPssLLszo5i6*?^ zp>J|{;u{{e;E9j_4G-PO@3*|0F6VLYdgxpHe#gH&n4YlDWB*CNqkib2ZTx=8haUPq zhqrv>p<6k8`9~hQiNoLc$irql_+0Uk$6T*3RlRJ%6`wNIOAj)LXt3&~?Hmpb@|ta^ z4f4Wy#XdI;@|vNY(V^*g{xi}`KjH6uIMPdZa`>Z>Ub9UO9G!mu;L%>Q{U?w1(slg( zDWlV6m^#`^H}m_4j82!ialw6qkj{}UvhN%{%wWA&xO-GcKN#WJHsPs zxKV(E0{pMe^g9nmy|jwceJJWBBc%ODQ7;Af{hvg=bP|U@il%=%A(n;@72wMS_y_Uy zJFf}w!>6Y2zb?SnCDQjF7U1$^`u<7*K3{-;BEa8ErQd&1fRF7;-#*{^O^o;rcVu@ZwErI3mDrZcg7XJu?k2 zJSz>KEWl9#zFvR_pPhbxya1mlz*_`ZJwN^a5f`T6{|NB%OVam8U7CjfF2LWoEPda1 zc^dw?0DmaJH-9tz&UII%;ZFqk57(yeAGbXX|LN8={O+@9_<~=i;nQA7!*9HphR42~ zhKIe8hVTD-8jii4hVT7%8Xo_C8h%@V-~S+ezxl&7eE!GjvGIbBy)3u~pSM3vzf;ib zHDd^FI<&ylDcg@o!;h~@!?8^TCY~2J6_{i1)6)vgG4`2hg{HncWO|{A^TPRQ_}9~m zO}dTMY53+zs;Q4EFI3Gjt?ELRzQf0j85gSNcsS~5)f}tKN0*p-;f)tc%y;hmsLZ_o zz(-}~{g*x}Gj-ydZw{v0IsW(F9Bh{V?VcfY6~BMboDrt~YW9~#n0ofyt4EmQ-UnBY zFm0`$ZcV@cqyRr9z%M^M!qlz)@4%L8u7&em+$3@0D;s`^P&))fVa*-BHsrmopF9UH z5%!$<=vE)IX4UG23z+NDf{3kXKe%{Ni--u0IuQ|`yF!FaFd`y&`9wr`?iSH)A|kj5 zEr@P&iRjr!MMUr~%7~tQv=5@AEsZTAfK$>yfPlQAHPux!*uR?U>dM;sdSEL!ddY%S zcFm1N83Z*Vl)>yb_%;oc=r^CQfO+$clTREF`6NVejLL`*hS}o+(WF00h~QO~5KVgC zC8CPwBt&q@N{A{RaffKk+eb=>;LjBijd{D;C8CeNEg^z4SVHvi=DvuqglCnuNeT-< zF?$W3WC4*n$yG~F^2k`=gBGy(CV3Fk;iAhXc@?Q%a9~S_ysi;>B}DLk%ZR*gOC+;3 zT<0<(mux-BJ47lG{O&R$mux-BJ5fRer@f45sN1T^+z5}qjL7d6(I%-xST2we9pw^H zvCKzUYmg8Xxb6NSG9oNgNQiuH5lxg4VUX%#4VyHWJFj~k`O)a7SWS3A}mNr zh@Nzd=qXu5u$mu3_9r`?w5k1`@G!bymp zcZ=v<84*_SBt);fMf9PJ2+MyGqMa@g&H9>*2y2HTqFG;asrZi?B6mL)9z{e)4T-xO zA&>f}-2GU!lo0*%dUuHCjsBa&M_BR{5zQO@SC@#|WW9#dWdWMV$Ys4a=rDwQoqmFOMh_Jvc zBI>xtEuyDnL|C1c5V;*8JKm8Q5=+|>qIX;}42fxsh$wQ{3U?wBxlJw+mh&YV5 z5nV9)Zb@hng&-ojV6@9#yI}MWBt!^dkP+SEuCXr|{h)*h@eeYhAG$^Kkc0@q6EdQQ z+#&k<$8uvM@bbv@5Fy$`M)X^^h~!B>LRDl$uen7e_Zs3{WJIsKLv-T?84-eHL_{}k zaH)=NeDx}+jSyiYA$s)+mnC{lmNkUuNQho@DQkB`Crc$lY>$ZOj;PBS0}+X#U{ z5~AO@l@TGTNJ8|fOGI}*DkDNjl8ETeN8KXom4z1ZOcJ7Am!{t%*U9sK1Vf34 z9=UFRcisQU{c_b1NhKk=&t=tq_K@rwK^T^Z=w}bP^o=}q;I||`LJXIP=&1v*aaXmc z4!l-Ega9xZ(X}oSJ(83VA$m+g^oYw|d+LwxN{A48CL#LcKirk*xj)L97IAALqUZkT zQqw*^S8i+sy@`mPpL?~t5{n;Y>IhMSBBEDkyEOe?T_PK!2r-lpEpcg#zWT20^+SB3 zgy>zHF?+7Xbu2pi5!7fPz}i7kZ8%<)=wd4dtF_i9BpkRn_0OPDF)(N)Z*FyF_*WoX4b6As$mih376&ZQJ<^2^GRQ zMO1k164k^qdGJRxsEBG}*;pnbF4}5hnXHfyOe&+&=h-e$RUUPyGy)(NRYX;J)D*X+ zn)iEo(vDD85!JlkU*;Co!XxG31d*^Js)a}D=8cOAF1%eH2M|arp}JikP+Xu|+Pz$A zE5zZ7sFrpwb6dgof}n&7VZ0)$_JWh$qB`?Dxq^rS7Ezsfo^A`csNlApGAaZSi>S77 zubT^0cYY$XC}NOBRCj*jnnmxQ^O)3D2w@gc-9JYkfL)a8!8!6A1rg99st4!1>bBYc z-;gm__eQaThtd-8 zwlAW>bC;;L?NsYTREYW)QQ^63RG&!N8Jh-VRG+xj&f9iACbbpz9LT61bK6!E%N9!& z#FhmS6`s4S;H=A{kBDuB9Ss|+s;phiKwt)LPUkW!>GA|&a!hQ=86`s39 z^_yFY%0*Pzt|6krbC;+lmaUSS9lJe5RCw+Z)wZ4gl9&OTMMPA1?h@6R=S`5tE9^B9 zQQ^5uR1Y5iI|&uGs)(rY+$E}QJ3m1Ra5H8EJ6%LncCiG&I}oMcp=xJ5Owtf^jXD{PPwQQ^7E z3Z5PrDk(4QuM$z=xl2^rcK$-DAhu_TsPNn+sxMU?bh21M?Cug#;kipx+jf2^l?t1~ zL{xb08r7Q;D(o$jQN8IN)msuOY)z9!}81v+ww$IPlk88olRKX-q_VAqB7jxE=pzf>0?u%h|2Kk zyFg`KLBpOx5tXrm<^q*<2^CusMO4NTstZ(WKX~G6q6}h3qlgO6UGkMRKmZ#eMN~$B zfQwRDBSf&DQbc7$h`2ztZ70joWh#1X#}rZFxyuS}+qpv$XYA&bQSERm&f9kGknDDB z2DPAaZ?}_FD(oedQIY#ny)L1`R#X|)>p7s3Du|t|7F6yl`0;@vi((_JjOyb9UH9Op zk^zZ*v@)ts-5ZdfR*0p-He3s;3fHCDQ6{3oE?ybcjxzVC8bwst1Z+Xo=pNPGA}Z`5 zwxGJ(C8}AM#V-+2VGFW|3eR1l+P3rKIU*|TU=~r~xqDQbMO4@TZ9%o!HL4wjA}Z{k zmQn2}bdBm$i5al{T1NG$duI4lDiwBbTTr<#)ea<4Hb+rx{+3bg@VKtvj)O#0*gI}P zb&zXRA4?U))^i!v$L=fm@g%WS*tu>&#kLW+&^WU$iz6$f*;d&2E~3J7*A?8+Afm#) zc@fpNojV#_qB`@u@m~>9VcWfk3eR1l+P3o(uZT)NlsN4d#dDXaCYG%(5K&>%zgQ|f zcZq7-&ex@}9XSI;RCw+h)efmtNI4**+Tp%bB#ARJ7Rac`tvGwjFZPRVg@gwpDm-^x zL6Vdg@+F9_}nSWvkg+h<)C-y)U@$sR;hc<#DX zA4_e8ToEFwZ96}#}%j zvMSXb?rcXQ#XhKTvWa!`6q1&TWkQ+@10@!)@mxog-l|x1?1EKGqJd*<(3SW|S`r>*D)g5u2?{^V92upOp}K%V|6VJuj@)y#kFLRFVy>5V#kJ(;b;K6 z@}#FY0Vxw&r0f9N14ig*izBi1njJ>tfm0cg^8?75IkM9BSh6b_>1q$#VU(WYV5LlD zMEVe*y@;b#kxV@mu)~>tWMx3HEs=u+2#+17SGr_9YdC{xq?V*6hms+I2@q)MUwuiR3gyU77lg> zqJefTf!3&UAY2tpMM9A(sZ^j{71AQ%^;%-1T%=1KiiG4nDAEs8dNWSX4YgA#$7Dct zox(V{_T|)7KnIfy_lH#m^ql8>OOMi&bG1s0ziZLdkfJ z^!?VKcgE!o!U0U;C<5LrTYB*UBJUuBl2In8RXlfKk%Iz>L||h>b-h$>E8%M_ghhf# z(_|0?vrb>PzOlN-5nYuQYS-3j8?*86r0l4icos>c#FCBGYHI6d%&ZDk1=a;R17VaR zTM??V7eTDeR)>Z{-YOL5kf(HRsR@OX@kn4}Fp$Fe#+8Y9RcEMA)1$07yDE#QPn41M zL36)D!H`5tEZFQsyfPSzCc8Sd1X96G&g&Q3Tf;4|9$TTigvzeL*B`bq7 zYig=1(-mru#99N9Dt547H_k-~RR%-Js^Fe6lN?V)lY<-&{5OII(Y#{1N3j@KoM6 zSIs`oMc-6A_RThj20(^M5Io~Fy#Z#M8axsXYSCmk+Flu0m#ht}OYVZ1G2TShN2b2- zP&lN#MBz5^!p$(z==MchA{I@BVzESirp2th>w2q0p^=*tg&z4ey+sd8rUHqowyID> z;B2dowVzoz@%%xZNjAbbBfiO@phz5wf{x+^Ef0p`7||nLd5r3_^RMN-4rN3_QJhtE+e;kEiHxu)=L5q! z*_eD_G8Ic`;Hb7x)rM9rg~M&aK`rTWBHD?i7feUL{O1m{fBxorQ|cEL4)$zWR`nTlkc(NCP= zZ1&*PaZw`K*w#+J+P?fLJu?hR&T1g-3p9 z6uyTS{vch|B$JUmM@C%_odP|QE)K<@!0hu;DK-o;f2EA{xYm)2+ zV%gG*-V@mX8MRTkOJ36X4$rfTaJ94X?&N+#+HMfM`X#+J>iXG^+20A@bq+j*9O5Y0 zw|K!O!G)5y{W8O;7#YknC(VGY<|y5_dFc+T2@Qm#R@5xWiuPuQMnuAO6!SY$Bev!# zm9z7&q?4_JOz01#gJHJvb?yC6Kvu{SSv=m8u&0D{4< zMVVPWI#AQln3L|9<}?sh24zOQ!J#NP_W(t?eTQC@Ip%CP7>h)-AWl?Ivbnt$*p(%O z{RMP=tp2MV3W&oPP{5z^0*(&UG}giS;#$wn>JCRj!9XHZ<-!btA@1mlDO>vWB9VD; zKm^KnU1N+diG95&EAuo|&vay-D;ydGr%-_4t&K6pJkuQAT5^S)hLwr6&epTjss&EN zK$-63Wg5*LWI@+s@1Z%=!cL~^uKmhtv0HE^2TJtzTY9(PdDd=etZ8)Y7CXXI7Pj<= zgmC}}2;aRq&Sy_8Jy{7iWbw^?+kqc&$_NOacvYP7!^}G8e#~H|II>0-lumXs4n9Hg zPUgiM9gI}AM}n=hs%Orst*>eihN4x$m=pDeEYvep$gZ>Mwr`J#orRNFP`K{5_0Gcc ztesV#rL*h^Pg%I=P?0c>eF5PiO{a1$S#)St!VR^~6GJB#8P1jg!C6hGGA=pF?P^Ab z)^+MI*DEDXrZEn{L4l9p1)i8n>YiLJ8p?6y=Ez;Ft9^$a{gK$AIHL!}-EeM#cj(a{ zW$)0MhCIfbrP4r$1A##JiCYZ9OS2Dj4K>ao8Jir&8=N`>f+zkV!8mD5GL+1*Lnb0l zsXLI+D$P}q^vYK-mZ8Cyt`Hj>2Ogmq&mEKG4Zd`Riw4i#TCBVKy$3|XI9&;Z?@&{W zFrH^6+*n=b*wbHeXmA|i1cIX$rdWgTABqGklO5q)BalYhH?~s@08Weo=>s_F{j{3e zhM6^@_2tHMImw=Kwh6+>AI+3@GvLfBl;)!E>Mf7wE?Pc!onE(n``^Vb#{pR&e96i# zz00?6|9e)#^;z6_cB4w&_Sd91dz{7v!jD7@!mqJ7dq@9aeHJUmDc%Z4eu3cfSGpLl zO<%XZq5tBovY~Pc1i=AhDA{qmWQez#QQw%;thFk)+BnUda0VKR)5?p}H~?!+{%km% zA`Ngb8w$9N7tnBg<+sK(Gh0zIm|3)@TG zO`nM3jV)w;E8%QHQtbSqV4P zI>+IxvJ9Ds!#?KO8-FMg#)+38yy*s=FrI^OK}&4yV(bc#HzKrKP>QH1I8xQA$MaiO%S{?Xt#1Y_WKi;9v%V$mlf{{wAa}%#ddcxzD*1j^tOEU$ zECj@Q;DApc9(9vmk3OXX6=}OlpEvAyZOWo$(&k*89SSnv|32^XMa$Uc+$xi;#r+Ao@eK^ET*6x;ktY8c}OITQ&B~Ydt);b;5X_wZ@G#&c0+j!evXp?h^^)BwG+xzNZt$^Q?p$^5W`?ByTB>%?06M zj~aw8a^Wq_qp9n*Z2v)D#B`aM{vJpB4$@^kLNaz80M@o@XbVhgI8jO|j%;#Zku~{OFf-!g!vQa6Yd1 zrfZ7hVvTXGG6?_b6q9h=1>xLHu(G8WN;%GOh%*R}KGSIG3t5gcN9JnC!ysw8rnptC zF;0vI;h#QZ*0?o$jkD~}vSY5MYlw@bHN~1p7zb~o#uF!)gthF1^XucFNEoMlgYfieCgGq9!nw~*o31IA z_SEA@aS(p&aFa0GQ}4*tjah<V!XDe!4Mov4atuxjGMUl@g|+{rkP(gnwm|3voKd)O5zleaD)^7%VLx8DcNhB$5KhtmWnQs@SB@?Q@_ax zZ>eAhpE%YyAG^9~ONAuIrDy7dfAf(^IJ+D-_cX@5SI*uPZj$($_YoNnS@Wx%3S&QK$^Bxq(s8kbHbHJ znuJ-VkSxrV`(ks`mI}$BAAGjn$Ky{o31>Ix^O+wvZK+6zH6G6iSDbAUPPl05+~-bB zTPmd4;)$H_jklPDv(Fau38ZM+QXyHHTR7q7r%l4yt;}pO^BK5W8Zy=M^**ls<7PvS zvk#dK`AlK9R7mcoBQDelzk11;2I1`Prfi`j8EP!~GXKK~pHp;}LD+>avo;Tderw_R zB3CcJM6dBR2c4}G-dcEmR<5qk!{%z*S|~Bss7rOi5AJu4K{z{e<>gY`QX$P2|IP{D zbpa>5r6T)mu_2$i)7HYn#istoWqOVMMdundK0JF<=STQ#kuZ)4gF*k+k4?g7XD6J` zq-|@VbQ;djIpO1*&NFJvPQ!6j68XfhH*KkqoG%}8!sV@;@Ro|~&X;V<#u?;Ta=zUB zO}(j)+wXk6##<_~J6{^|F>kjPUL^MMbyw+xZ@Zrp-dcE(i$2cXQQow*P)g?b2`5~5 z_60^Cvt*9WeVoU{ylHFU#bS;BaIIeB52jsc5Wd(&jdNe)Y}!(>UL<_ncAfCD*E!)W z73;GS&K9X^%UstKOUB-xZq*6jc{*KJ5ja@H5w5YB1NCSqazY|g=!9QA z<8p)Wh1m(`Gcn&%A^EHC|GQ53#4X>@32&*$?yt^k`DbgPq@7}K>x9?+G^EO>Ma#Xv8mtxK(Fy9-mM1VWY(t676@ZYcx&MWBH`u_b;6JR zl@s1tctKXe*H^u}-iyb}b8+nG)|x1UmvrZ5Q(1j7#INWPCZ_A>ic#UXn&$ zl5tv1O?7R}tg1i`IVBFtNIF|^cGK2E>ByD0Kh+zi`#0MRX=6vOI9o0sgop9BK*BOM_F$@_9+vaU(+FB?b8FJI11#AxS{qpY^IN6aQ8F2EgsQIk1 zZ7q~eZ`gi>PPpy1n+(G2^oA^i^Du0;R7jrc$5-iumwtMyPIya2c29M-ZH!Lr8{4E4 zob}O9m>`w2>?X<3x_t7=9AN&~E~$)@Jio|`aX2r=Se~0Dm&7bn9jS|g1lXDP9BWqLu72pxjPOg}(+^aZq8>|*4@5)Sh6Ul|Iy;Ki0i^N+1`B0CLZ@XQYP9 zj@)T`fBEPVCM46I_=FXBbf9L|ES4+GZC;^zA>V;hng}^HfK&Ir@q%8aAN;}-W?8s{ z@od2+qSkZj;7Qq0IkncEACd3w|)q@R)SYndxLJy~m4sIWMY^$Sl9SnR<56EG5cN z*Q*@b^zEJ@tWE15n#|ht&{St-Jlq!2cUZNzMk>3taC=9tM?+M^0~4<)z zwHt`ox!5KmUvqd}BG$5IzTNH{>)}G@Uae!har@U9Hsf$16I)q%c{z>(YMEPJUS4iJ zKm;|lqWplP9NT`GgtFw=6)lykw8VNX!Ok?XYqb??-d9C?;ip^m;$1xXa)t}f(Q4vh zMYf3W5fMGf5gj;1M}&_{L8Hk$(^DHxJ(-9UB088C)g!=O0Y=q~cM1i#NPvrpsGQ^R z3Gl%Re%oA&>J}5JFkG3zr7DAnRHYPuD%7JY{4E7<;b1}GEsyz@M|=xMH41Ne&9}Vb zTR6i{f6D`k>9-2Rx4@47pS^d1ljErFg?sg|B^mjFjd=u2ZEJ#d?VZ_~U9GfQd1bHl z^4eNS-j!^Fw6=R^YIfT@(>?C)+0`P;*9H;@HzdFf5C|V{NC=mZ@Fm9Jga8S70QrCb zArHs{xcDaF-T)yXB*ebI|EXv9^sH8b5P#qAYg;q3T~((}ojP^u)TvXatXvy3tc`Xq zobJ@Dy>=FJ+H0t6l_(i$w47g@qWY}affP%}*L&fu8g{Pv3AMpl{<3W^d zMePPJ$ZkC(y8~T$z5ERhyh8r|Ime+Zke>P>=Vd+Au@`^HdD(jBMULY!!39(S(z zkh6Imb5WK1uxXc+wzbCVUb~Sn0{6%zPVbh%dc%ts23u|N z;acBn&!OUo$6;fMM}uAsmpZL=v~Q6NRrOlc`aDYEQFOyMNYV2!y6t|)an3r9v;JY{ zmwKEn&eRZl;&GZKFM8Nv1_2XpWGrf4Y?_qybVL6iBgl%&XP@M#Zsq7dY85TVq^Xkw%?jgL0IX!>^0GI2s13eDG zUALJzn>PZkV3{tUMhP`%pvWbs zK?%r?i94S>=&d)bpwZj+prqdVoHoLJ0@TBICk5cgf>eBWroKt0;#<+@ML=M^=9CRX zhl)oY`VrRu64bvz*N=H&;?5r>0UiPZ8#MwTz@aA(f6!>YNMlFrd*t$tAzYtVBiI&h z6LO?t1dq$#7{O|C#|SAB=`C|s92n>VbxQE6RI#XG`n z!{v^g?1+o06DKh8^B}C(5Y}~rKx{ak17ICc=+OWK<7R57A&&bQ?b;!Z9W;U^s;E4AEkv2D7mn7~&_)l^Afk{)==$(YHA*II>wy!A)xhX0p5R&77&B^^b_z zb>kz@Egx|V&Tlx5Gvqi9mIFUcs+-eO zbsPtJ7-pK+J5J9V9LM+W!^v4%Fjx+2yoAzJf zU|uG@?|Q_eaHM87ArlWd&ZggdisMYm#J4)m=Bsa&FK?4CPs;BPWAY9qxM#}m=g9AC z9A^{s0ftPy_;6*)Hu+tU->2pGS!6mR|L8;U4GuIR!uC2Oe#CJwQ0e(?>-UGT*tyto zde_G_@3r{jb&k_}v840QVDk z=E~5nQn^$vRqjIKED}kFJ%vB#@Zsrq)A;kS6YvfYS}8}PB$aineIxW71#H@g8MSPjG|vhBjhPJE2uV>>>s#YaCre%xy3(;cUG zvQ!$Zak>d)u+{LAdKfja^c@`a>Z7COa;Y894UT$cJf+%lb$IafLe(!WRBNSj$!jO! zAaEb76f4hgoZb!i<7)MTq}M}|^Bv~`*_x!NWNVsPw>pnI=V0s22W_6d=!eSFn=iTs z9QY&UW=FHK10GiV+?|zw`Imp0q|bj8D__%(Iyt`afLJHxZ_MZrvv@G0*W_=^=;}9S^tyZx`+)il3(MW| zJ?5CZzI7T zSUZSYyz19|USqPAC(l*ax>f4x>8R@xT~{Nl=76?Mwwu@6pdbIpIht{$1|9neFE+xe z*Qn)GVS6TS-e6Z@DtO`v{O-X1DqV%&TG~-;daV|(owJUO`E`ir9Ca|YUr~P!)akXv-?4Dj!V`0!(VR^MMyA~L`G+(ivt&gm=mas}&03JfgXCpX) zd!KFB0*jedifMz`-NY z$Y2z<6F-<&-^Ik6Ymm7Jz5ngyoxz3HLe9rf)9xIP;ie$N&j8c-kG}f_HX;Zg^*LHS$|YvB&AX z^o|onuU0E2AOj@MgBpt1fVMu+feesNVfYX6~lH?xqx~cmI(YJ0JFAv4BI%!PXUY zg(msMsO%%_oeas@zKDAXXU)Z$AF+Bnp!+UZ7%*%uC+!w$?;ng;;)FM4hp?y}uqu_i zo66m-%IyJO`AK(&!QB$%=Pg7x+$IV1^*-P3qL+N=XG|Au$|uy&jN)=u4685G>Z&QN^&yD2rgo|})aD+cs_Z-wn!;MGNT(6G)7$s59UXiVHcEZG~>iqudz8`UKerMQRLUS zO2!l^lb0G^5UckP=yM5=6ZHa;d@fm_O;q&`>wQ_c6-G%lNFt@ZlSRZzMe?Mh)JbP z{uh~oZ(QwgvEyvIbsaP*!7{Yf-g{-02d&~lW4T#uEktw0T6O6@=v7yeh7$YXjeb?# zKEB>@dY?-^Gq+>^^!l7EdoOjI&KRrcrMf@g^n$@^7-&|oUbnd6Kr}$+CMQtULhC&( z_0)T?zsw);rp1S#w@eUUMQo+3Vxsm2FE%|)IO?^irNN7F*p8}P_Xemw@5QYstosHC zs+fQ=!tCzQDakvd}%6O8G9`MN1d;^dskszqrfQCtG)|E|%)(n2D6^0Ex zs$r|~TQRQ=E^;kuu;%ci`xHD>wdmKXVUR>&BQ-aH-x|E8<-aNd_H5v;<)9j^w8%jK z&smIf`F(cd)KKg=Z|QMvbSlG@dX?|mHM*l***UsRRI%R}X1Z#S=3N6YofD4(0F z?HU;wE$^!A;S(pbheyjhckrE6K2qU3YrA(=s^#5vuey75bm#8TQLj8YSFO}X zz532wb31pw27ZFY4)W-d_2MSAK2! zRd1g9t&bJf*LD?-?D_9c`|2L}!W+qDl*zU>1~`R%vA|2+ri-~Q#H-}}Jp|9ZUd z74QA%hu`zfJ1#oXciSa@e&b8`ZaTYZ<4e9#{+p`?fA6P1_>`y3J$Ce#eIGgemD11d zEI;o=`%|YL{QLKRJU;OL8xHfs4>vz?w6tmR9pC=d-+19q9(~aJ_CN9We=GQx8?Sxk z>z?tf&u{$gk9=YHzkT5wfB5Ua@Z+U#-?8DTFC4u6uOIqm-1q!1_x!{6Z+Z0H8&2I? z-gouOc0aoPE1!DfPrU8qKVJ8=kN^G~y|3T#mB%){^fgD9e){pge|hBWU+rps_mi)_ zsQ1_Y?v`60edh9QzxvMJKX_~V>34niwIkP+-tq8VZ#cf`s(<>QfBNalyZ`oAUv}R! z2iL9dae9anFa74}SFgPJNa>w3|NR}GE6so8wfDa1SKj#NlLN0m`<*xa)d#(75o0{wm*9Dslm^% zSH1qZkH6>}iTC*reecsBD_(l4=ciux!7X3#ZvD_l?|C=1`^L+MuRQT@9|)g&{qlRyeCJgk{=_G~_;0`P&VT&=w)eea?vNEfKd;3rQ`@{e zcIB?e{^d*G+3<^_|JU``y>NE;^?&*1`;I>41?!&ji+>-!>*p_j_ZR!__}aT3c=(R1 zPPRVz*B`j`dwZ{Y`wI(+bIJ2x`{QpuvGo9O_=9h3e4qD%=pQdT{DJkqGgbQ6V-Icq z=#ix_@PGL9BOk4P`)A(sPw)PTpStM%pG$gYzV-Vh_wS!J`K{9E%h}KE{rBLqM{c_E zGv9yo`-g6RWaiLgfA^m6-O7ILsuz2$f4q42$q(#4@RsX7vGwBNJ=4ic-}|oDe&Ayt zI{lo#x$4h1|KWr8KJ}{KcOFa*~{F(i~`}Gg_Uv*ycso%e3;H%%C zzTs8>_O^$Q{_JzE_>*tnb?+k|{Nw(f@4R5*gW+?(bomX%S6;n)-9r!docYp+zw(8F zf$gV0{@(GHbN^?4r#gJ;fm`a=&WzQs9Q*1E{_LY~`0$r*`=gJ4?+-V9GbE`cllf6_days@4oVukuRV4nXi5Oia$Ah=dXPC>YsLp{_3Y+_vuOW#IGED z-!FV<|Cjr&x#IWEer0s_YwxUHUhVmpFFfa2A9==Cu6XtpfAE`6|C`@9_SW{hpD{c8 zt`C3f=~vu(*Ux^g`fDHi$&2E36QBIvZ@>PVlW+UEm;U=dyygq9_}H0`?0@GcpLpM| z{lbF>9{BcUzxtG&r>GNXS$p92m;6cNUF+Zc7dwCDCl9~lYyWol#3u$e{NAN^ zK7ZZySZ4H+Ie}(^rdMrQ3M6KNCXW}OmT5T-D^uVlt!7Kl>rf@swt`V*DI+!;qLluQ zSJk8$!nAcOHDcW&erFlHKxUJv41^ zl3sVPT=n!|Q?#D63OdUH2lhVUm`BDfWZ3{$*=;({CC{Qf!s!amECj}ns?Tz!hGbz{ zWpALu3&TUh!?N%?=XbAkoR42gt?E$~!4wEzF96#}z+%5;0V7Nn4VV(zp`CL-0dJV2uNGbugxKsj`PAJjvR(Q0l6@^KtyIK_@B`1lvRwpq1qtMdn zh8GMjCA_7}fM)`pkV$k1{X6M6&YNU^-Qtk-mmYY;-7DW8b{uTa(K97?`SBca9OvcY zwR058ul)Vl^?*4wH15ES5#E%SDTCZ3$FCm)TR#gQ&&0Y|hfGGA-Z^R&c+jB2%7gN>o21;^Zo>xCYihFYyw$cr#&_|^&&IJA;h$`C;~;GMBU zVJ!oZEDa(G3#`tfk-=uG5f4W3Qfsi~r5Cr>zFQc#>VsZnBy?t9j?!`T$P21k?&jqQ zaJFgAm|d_)&DIln!Mp~7RkW3%JvZM zE!~MQh*(K=FG##tr-IF+k-_<9t9Wl{tUyo;tU|_ck)gY?04r)_@K~kCBEOZQW2Vn3 zIYY%v-N@p#&FIU4kR3P@JsQ1p^R1;;Lt`!}Oi7KJz|9_)k|LCzvb$sp3T`%}lzp!O zi}bLqImi|%RI|;0*~F9;F`G!uRb3(bUDunoGs1+Uc<*@C9@ULL|wxMKkjh0Ra{hk%xwRIii^2VCif z2T2G;j0az@6+ely4`JEjh)spB$vn@7qXJeN@~DWiPF?Fb&R>AVr1$bM>7ep_?C_(L z9pTgWw_g{(;Xm~W5Crwk^f(V}hR^F0Z^2?jpgNY`4ab@QEnIY*P50ljxX^H%P2Y(Z z7igh@4dA;vx5BVlmDyD1j>GA%|#gY(CP%MF@P1rJ@Bgdkc2{lYPNb#8YfyfH4 zFb1!%ty{LS<2+7yjV=4h0wXJV;xDqDr5&e{IJ3fQ>=tjq3ts5?b8L`#UKK7RH!g$; z-Mdx|o5*+Aj}y|9w{96D{$z(IXO174m^#4RW#KB&CQpGF)w(Ehhs2YL#cX-OuP(4< zztLcG960kD^885~+JYyICFLPUbGRJEPjWRbIKOmcBH*=TI0i{xA zZrsR^DPUc6mxWxZFn1}85`MZ=^Ad0MMpuSZ=Hjv+tfjy(bL)I4H_*XqNbQh>TU%KM z2Cc*iOZ+CsMt8uY0am45XuqCfO6JE{14&nk8f!&-$q(CcV}*GEc_%U+B#}?UkNIM= zU4w4N-aN*PUuS*na@kuY9R!)um}GuQ2BwQ&3l zG5$PT_M*TK=9znh5iOmI5UB-2fAhD&H|J&cy&S_lGA7vrU0C-JGeuIdFTvE(NpfxC6fSt7tT z>7f9LtBMe~u+iYvgf-zh2C!Im#ap+G)x(H;)dl7=KNzQeuLUuyk}DDQH8MWn_NkWM zFMkZFAH(X$4)tS1{n)8~>{35Q)sNlkN2RQPY1kDFyrQ93cJ#aKdCy~oWTnN~1I)dv zZ{q%akn8=Y3ND+Kd`IKu5Kq|TF$M;}{8Ep?CQBBSdf)B+artvdPCH9Ic`3e!vbNJ;cOBCk28Z)I-+iia8Z^t&FjP zU5CWj?NQ{IKhOELJUN}aL_;IwDxs{(!M5YwV|b2><6B$dHwdvY0|vL-gcTauZy91jpS=y zTMP(jU7z`pXkF*hsBm*Gbf_Pe8U^3&VuJ^XSBl!%`Fx1E;bPAFVdgF^N*!feN-@J+ zo4J@5*k<$ODP!qO=TxB5*}G{_>0Dh^sC2e`9V(qCUx`ZRS-TdMDR&MvDwBH+dQ_&w zniZ)`x&L32`j672wEQ;;(2q`$dQzxT5NN{J^FKqAT9c}io>R$BTFe}G+G`zU-@009Seerfwwm?JRiS3x`EsFVZKe|r`D#}7)C7kwC-h0P1gPVL1ysSy z=yU~12s&YLXp6$?*$S)NBM&xi%MW~>RKH7rlLL>jkC+24u(&-f7X(zm&u-qv?uh&( z5$D&BE%=Rw-(oXK6gKC0gz?3O%9Y(1Py78iiTt@X3~cS7#v{_2rzVfHhF|4D%#lg` zOBVcCnh|2=nG+sWuhHN&R-gkM$gEdZ(p#A|{D8BSux-p|a}ACTytfS-29|EFD9+-r z$p-_zJXjAKH6D>Aj#mDS2H_@N$1GX!5*Bb?1DH9k%^T7{2Q>V;RYEVaXo1CR1GLVI z<)W$v@nVFJOGjC-9zG?}QpZxnqI&BV<snu+%IwFCkj=+#7oSj-o!D2L6^<(YS`ql^%BMzw0U{KZ*bPvcXF)dR~K2qw7&1; zSc3=Fn^{(5mHyd&Sd|8~SqV_^jKv&Gp=j3$uiO=)K;^8VbvI&o2@zwC&-($HvCfku zgPJC5AW2ROXxV-NO|P&HT4ozfR=$(i{o%&QGj6(Lmi5}kJV|sxb;VB1-EInOPmj8| zCy+6bvBDB*_zTfl+qK+2qL>>e*JE_sbMzlY4jh%t&odr3Ps zqJ)Hc3x*s&m{&C|M_voAdbAV5?is6v>`bXtI?KYKNPTGmq`$ksQ)EMV0UOU?5{3;{ zC!jJzsmiXzo8sQE-=L4C}6m>}g$fvJp4dr3r` zR10awOUU>-$6rl?Y(&5i`kDF;>VvYEAWCVoeOT#2{E$NeGtflrEWSMK&#b zOe&1$@);8*U9{GgVVH0PwG`E^V-+$}GG+u+t_UOc%jz7wrd184d$?P-K&y1Vrp<@X zQfg$*NmE;ie9ynV%Eu1w(|TX+V+Z#sP$moc3htFTu%J!eym^~-LUrpF8k2)!Og6(B z7e0$L3YGU_)r0?ET&nr=K7PRlH>kV;#i>j90`8kARimWT;>|re`hsuQ2IRt%b;o`M3)%5Ex3aap5Q)8ajS>W_o5~=H`i^k)1>3q4K_oO0jZ* zIG+PrMjp65W00leD`n42Pa1 z}u3ibF3 zkI5&x>77PgziK;*c#x0-ywBtDO1Z3)#f}?t1za2kA0H}XF$;fqnX2cgHF?;xB_8?p z6)F!|0&GZrD6|oWr>fSzCoLZcwbfcF(SO(yHjNdfY>xt&jg~OutDvSG4BYg=0O{>7 zB&0-+6nKMO7xXA%-nr4EY(F4+L$Kv2lUWWChIW>Bj_uf0E{l(`N~N-fDq%btpO~1K zI8Wf^^7#V?uQKqe+}s^^D}piuY_v35+ELnJ_dq(Qy9Y|#bFCq1NB$TP(>?p*24yO| zROxuaPp@L@bsu==D@dPvwlWT80^qM9e`Ti7wc5v^4r;M^{l-j;bFry1C~~R%hTt!x;jLlPMka-Cd&pp8N$W+>K_@ARuvWNYH7re} zJy{9tPa=96^rgwUL#5UCtV*(H3K6-!Q z)~1rw*+e%MI;}f)#$Dtq?wITDVJ_Kh>G#<^vN+U}zCx;aaj$Dp$L-JKmK-)GF3u3B z3wX(f`Jg+wL<}M_sEv>0lFG8)^|=SIr{(s82ez@3V@c>mk+;GOO~wUHVE$1w!SA!| zEH%O^2( zm%f`60Epk@%574J9-Uz#gqyJNj3N3O)uVQh_l2#M2zQ{dzG^=kDwju!L*=2JjN%?K z5%}mv3V&3J+IxiqAr& znD-h=G{s}mM-hSBN6)$M0tJ889(aoR#wQjyIT z_qy#sEy1Q~*Zuf{AB)Va?loe7 zFxpT@&*irpY_)X@?Y&9qXsW0E4*51)qezo8TDC5`;6$UbKMYc^uom7IHk)A}?7b8q z;Q0rDigtuRo`Zgan;gaGA5g}(Os-&_N3=o7Twd8xuUEa=$XvNRG_q^BQZDbTdftv< zuQF8ehK6dReD|($xxS-5x4T*&9T}>ZhrC_oQO_HxjqKdHQ;;JCe?|rpgha46E7b8) zXjn9)nb=3~?d$6!Q?e>p-0RM@{YK&k#UyISNzn_c3t@y=bDX*Kiq~9r|NZQg*>+;= z96%_1nA?w|541^e!2rgY>opo~KTcEF2pBnNw_3KumWFWl2?McVLk+k37EHdEmHU-s zq#ZhFXznEK^+1WTz{AT%3$1d7@E&5koQ zM!nZkjkuJleL=k|n4(h0MphaWJb>(-E20WEVDo8i%{+C(>M*UMToHY0X5K1dEYSF>A;9o#mqa=XheSCU5!#vA8?sr< zlr{nh%zLa?2t4buvzCvTWPA|^7F3h7f+i8mVlBO^ zI?EK8<4PK5X#)EL{6OOGx) z0y7Tkk?L&sTPGOJ&KPj%^7`bZ!XE1;kY&7}=tHjX;xwL&9xl4Z;=Il(F{yX0O~_eQ z?2Ngc!=9a-l4j04ARRo~$&rYFz@sIvFwIE88D#zYdJcXb)^Fey32?iN1$9pn8d`@+O z2r#=x>b4^(0P-@B?l4ZdcZ ziS_rN3XYS5u8t`ZNQcEa-Uyd*1RUoR5WOL4dX17e{S2o{q>UhoI^6LDQmbF~v<2LVXkK8c;X;4kpyM zU%9O}imT8^$rK8sk}%mHosry6##9>?@(6*e7=28silQ=^ihLb**IjF~yWSxpb&Rq7 zVSq3`?dpQyN*w6v%^I0d?KA~4P%?TOW9-x*B(*$;Si=DkvYAP(_C(YmTcEf}L>Xb> zZcR)GkSEY?~r# zwh+lndEH!9af{x@FmR5_t3Qf+&3csC!RaS8@Dxc|USCk~Ysl4fHY6)lRQ{ismQ5sh#j`*Soy zBw@?1#^Ykn91yjMhK)CQGmKVJW>Xbt>O^Zk@@hQAM{V&=-xW&!&0+&BB*jzp`~DDN z%b0t|(dkjR3G2Om%NCeM69%ARJ7Mkr3cMsD$%XZFvRl%O1Yo5XkxjINe zPi2shV!|7IKJuET=Hv3s@oOkvUXB&EfPWF%@R?(8>tNK*fBaZTHYmIRLY~fcJCY=9U`wY z=mgtPbYy7vj$I?WhIbG(^6Qt)aQnPQqo0VDr7F79&UODn*yQ(z^}1i>RKfs0f+)n2 z*C0=XtPt%YQ6bP({ekKPvd6>uc^m_Unv;aML6Htf#w*Rauz_H3Y0j`{X;&HF;U^0- zvW#3rnAV7mrF~%|jE>UQl*(f8-_H|XO(t6i)3Tq}y>=rpa|W)bGy^?cTA-a01>Y`u zPzFvmWxbYP@>_m=r4&ZF#ND`B75kv99$kTqII$lNwZ+SdSUW$PB&-2e&-s7He;XGMi{ zh`+p;xgl;Q^6M)uX}Tz7zk_PW`Y4K$=m6U56YG;1F;Pw-i>YD{E7&P}`b&(?9fvY3 zpFsiP&6YgBLA*jStmyiiMpnf>{-VmKt7OTUK}rnQH{CBc)aLEBP6$pl@1<1CTn81%k#_#3MJP8 z0*7fYsD;h_6aWhc($c9XT8+@F(R3Qu=}e?Y_tKdS?l$E}4Ko2)7RAx&!eosHiJxH3 z&V!F8Ft>Bf0@;%-F~ft}O@4q#Um58kszv&N({v!IYr3tMch8lh{E3w^uJH95;=HP2 zTaXFUm|tf>DAt9Yq;4Ljf)X!uk$536hr2|Wu>F3-t4SEGAP`=vt0*(&ap`hqL7r{w zfVdk+g2|RrsaCBsJc#|o#{uvF*Ok)=ObBp^NEQV0+vTZK1(CB^Daoqpu!u__bBj3} z(ew7*JUt**(y@<7QH>QAFZ!+iEId`-)~07>Zf3Xgl}AU1AdDPci>R@c z#fl11V$EoGXnJwV3%q$Ab*T(lro154n&S(c?Qhq*;YUe!>xshH-lSQW6RQu+%(eItvCa$P}tRA_BmQDJ3P?b0S#5aazfbIL`}TIuTM; zShi}cZ;%!Dvb+0HQXB`Nk%8hz!k`uLn688*gi%?lzgr09kmhpWM&Vywubp5%3EN32 z^6LZEpJAhhS84!Y@EM~i%`#rF!m4CeQHxX{l=GNv%PtN>t{8(js8aXm=|;wex8kzd z0qnb95X=YMyK;e^I#sF-mRvR~7Tr0Um+%GB+chx%=Iqsoi$jke5>?#pMKK|J-X+CO z=&Z7FZewgL48+;n15pHxQ8Ye-5Zr|1LPzMh*pim}dx~1N6}O8Km^_UH%|(xDqj-9= zS@s$QbQBVslz*|Y%<7)s;I%Q~bZ{Udlkhe&%8_3a;X&aH-BUr0FVQ?a&I%ntH{va1qbvb&2@Fo2+^nm;VyJt_G`%kYkJWlkJu^KLOP%3!VW4l+}NLoQ{OTtaX_IorTN3m%fc?D zCU6;WM0$-FyH&5S&zRTkH)q}eKEVf)*!E34sE$_lIPe&BiAX85xc!e%(K zC~Sr=fX(oF+h({mRTdV*^c&a<@A-PVk1=v`?S*2<0tsZ1>@4@8w7F0Zgf%)`4pjhb z6^F|KW6amCY6njH$vd=6a4uA@Rqu#PItBfMMfnVcGbhLwZuJri?`)~!L zBOK(NX4j--v@T=04-;xw%4Q1eYey4Nb-|QL)#F9g1s@iLb|j(~be2|B(v_wFNY7@` zz-?xsl`?>*_Z8r+YKU>X)9PWZlRAviR+??kkfx9>smj`6C5xrDv_e?#g%#9#VOukg z!%bavyI3tu1T|wKP(}7JDyaJ8pUeVrJAh8O$u}s)eiAw!ahop0hLWN7)ai?`>Mv30s_q?JH)2vrumW&w|lD&6q%dh zk?%E*v=Lw~n|3>oCSb5hK|{!TKbV)?A_s(3GM(O;U`nLgb5q-I)X=N;{4jkKTQ>>^ zMK=3Dk_BI$Fc;lonAy}Krj4|ZiYSeEz^`s|aRZ@>Hr)9NHCBRZ?n{dJm1o2pNF_D=1&Cv>7o6hJt$5@jRQedNCZV7!Y+(5;Kb-S99Hd_0VXuHPh?eXTk)ZY z(8ht4j$(G6Rg!RURUsz!0uF{zx3aWXaMQ|(z()@Zn`Vvl1kpJ&ZEjz*dDu z{eirgr!$%g8Iv~U&x^=pR!J$vj)!TUpBBfRYD%TIN>GIU!?;KXgtw_hDX?`+%<~|b zNo+2#tX3ojF%~SKR`ULEIe_&eKNYl+{;#Tmc_P5{g*l;V0W>eCQ;bLAP`IuL(Fuh& zJxyx2Ub%koV>&#ELxFRM6<45G7RDpZnv>1TtfFF4GIIiB1qDEEPZ!EKhft8!%CiUJ zuYSZRHty{rP>GyCtYvWLIX|@%q&&=N36m+`JI)FzwAG3ROYrO=O|?QvS4H6{jH|P)(K*D5>t5R zhTb$1vhVDWK5)ZJD!WbQH}z) z|H5mKqRCXG#Y4WO0OrZ_Yf5T;C1%os=TOzvQ!GWQJGHUFTd{M^8xDq-Is=U@wp$w_94~0gDa@IsmvD z$VzV@MF!PN%a(1Z5}jtHV1bCWuAC!vQhL;%e*^>?H#*=+=im{{aGv2Ca5@2j87Pi! zx`in_K{hF4D##|wVS8}7gF4f5(iu;r5t%IF$&HhaV$xcdelJV{vaXIKIsCdMTgHSG z5^4R_YFOHsAxB8M)^wKKwA^ywC(GtxRchIaG(U++L~Vg;BEu~(o&^0Ej zEq_#Aj0hVK)>lvk<(cOi9lKIW78OW0Shg))(g;#PX4I1|#!eP2qO(FeRRMMTT;}$> zOs)-5^{YH<1H>qNh$g3wR!#blGE>__oR!(Ih?>6d=4ltZ=d0&BJ-Ra!)L!UKf^drN~qDvfs^U?gg1NX2fP8$}uv#M|OJ} zp6VXK0x4dWd`DwZ=d(Ir`IG=D1tx77)>&xV-sCYosbFL>n66S8P>JRRQ(j2`B`b9n z1EG*M2dA)=JMmgDcBP#lf}o&1l*D_pSdo#%VKpEVEPSGrsS5!?gt53+Gq}=%tY%`* zPU=Q-``YLs#@4Jg5XA}|iW1?xjTMk!%F$a@#+F>!1bZ5_@*9=KdTCF^_G^3lz-Tvl z8we)#m_OI>tHL{%$56&VV+GZi*Hn+&scOS8{nEA|8%QbJv^4?Z>IqSPt&^vc*fO%4 z;ik^HQ)ZnBnk|w6L9<1hjwzGJ+HEA%cF5OhabpIQUDGb+;szybwT`*QgHrglz%Qhv z!hW1&1w$kqjH0gqG>dy(&;h1ew_gVJP~})hg>W!L)-ktB@e=%G2+&$$VH$RLz)svlrDcWsGGhV$%^agSMN;Xz6bcn|yL+3uETcWz}{vMXoqkwKU$) ze`@oNis^VQ`CW(1X7F|Pnk!5gsa)t>K_b&NY*qNF`CNp1F^F}r252ZsXhLKr3st|s zM1jh0VP8QiwZ*+|(14Hp8W;p9$YNj;m&y?-^1vB_$Y07j-@z)mgU8_a!$nU*%VH-v zA|n9Q1Sc0buAVQIEmYCm^mzsXXeReQIoRJ?5Zon&KCP>Yj@HFz+eER3II1(gwrNf@-7xJ7Q34VBp} z`K^w-6F2SKf8gMun0E%t-e@2s^=DYvBZl18na^x*P`>*uqMaQB9Dwwto>*fp_`2zhD|0OXb?FI1#T z8-`^bR2AHw;{0*u`iP$jYu~xyr=m5L{MvX9#96iWCVHt1;8_tBt`W}r z(2uA_YZU;0zRY5QDaJ=vnk`n-lghVFhesB>uS|rRup<>(F-50wuRVAXgfa_{6cAH| zV3tX`@Q^Mp)Qa?B%*m{;%&xO|d`OH}qlD|tWaDaL63w)c;=B|pwx&KA)Oe6cRahHn zmCk)E;yCHu$M7a#5WL$=s2LK_Tla z2=LdkAt`?;Dq2AzUSe)>uh82FQL)n{#*e`6_)3c(Mc_%r(FM^lsl~-%9snH~a4s*0 zBp_xqo1lV8SwYq!k(ID%dr+nzt{~#|rVJr^h~LUr1_Yt~U|d#j`bruS3Ti#0ess5TTy&Uti22iJ>;+w@-B5ip3wHKlTZ zvAt}xY^h(g`jK~=iY#TeYnR|e@)1x(p6%#fYL^(*YJ*G+1|^QSvEJTZ^4L}`up(p( zVl8;J6{H$>9P$ymIZ0aNHKWFvlowN8Rfw|O3EuJ%(u#3f4#!hol};2kRwimqKk(y( zN8}1;WVp30rsZrZwgS#fH@)f-4{Bi)Q)C4kh0!cl=vECY0Do{8tYqmKlS~%4I?=Q6 za)klZ81WSs+fn^=Q|YoVah`H|hpS_)qCQew()?u%fXgC+if|lK&Q)*|k;f-$sd$9q zbdhoz!6QRWS@uB9>O#ujPLu)*+Oc&&F^U}v;v$r$X*IQK3LWuq+}q*;~fs zx~)f@85H?m_e6cEMc6qk&wD#dYGesVCOyKaVuUwH@sVU8a7e+fz&QTHCBD&9pW;{t&oC?ErCwPE>XlgDJNn3{~ufXkQs zDwo|M7+i=^%_sT(R)!3j(Sjf|MMT97YvV3m@^Nl+=0aO`!jlA_YVt{4wEIHI!| zYT82LT-;Sx;XD3c&0hJprx=P{7=N9EHk!c{a|kWW47c1ll6uqRfu>dzBVSxP19nZT z*ivsZW%RUWUX@v8L@9@9wMpkuniC;l8J9BZ5Ec$%Wh9q>+TMrj>Jo`^vALn8mdZzc1iCl zJJkYBG(n(%tR0n*maWQJt2(9Wf;!U154wro)XOxamY6#xIfM8iTe43V|0|vs&3TVn$&K&x+P=)RZ_<4Y6Xw7l&wtGR(f9NDHW=t=May_PgX3NXJi2# zJ55WAj5L_yaqP{fYQpL!dsL_=qRE<653oM>u09bi+ zbm4L4QW0hL#hqtTlQ|sD3tD9>9A_?7V3(0P*lJ~fjw`P#GNCI-gQ9xW2&6QMGAVVHj473T!sXt7eQ% zH#3k=#5h6OZ73_7uDMoOt>{-7lCqEzE~%U}U1Se{N;OBKVvpj2d}rOxrv@x2Zgx6s zPZL&;I4>^LYQ-2D2b*Qrv(e$v(VgYd^i?mb-D^{g8pWDC8m5gb=U1FAs-d#32so3n z$r%+@vl*PGaJ3N=+1Y{@GlX44dsw~U#S2WdXb$(t*ydc<$DIy{uG5Zqjg}q?cgq67 z_DvtAkVgW(a>5cKLC{l7T^8e5Gng>3biw;bXtUeAzr+It-`M_*QO6cT;4XD#(5ii6 zX=Oi*n}*hW&yeE6^hHH$ES`VMkW{)d9C*$TJt=A_-s?$}Iq*7Z7w zkYcVfN>?+UzFovH0EPV_uC)Y&2o7q2*e<6gEsILb-A)0s^pPoJsgl^*7D**>#OAq_ zXBji3nhVXAY6nwaSljoeFBQsby9jBHxLl&4bjMdaNYGAOOp7}-&q_vtj$moso5cPyGN%kt?^EqzNt;wRk~S-X?bQu@b>Lqqqx`g7HJC@a~e6KVw|TVhh?q?~!V9GE@+mL&hKhULeMhtps%^)~ z=jrMK!W!eCV?H+{Y<*A-o2>><_yBAAF-7DRnKg=FeAA(7LDGfUb*Xc*x-pPrNdW#^ z3oEQbY>U0pOlOR{)_~XJQ>)8s(LSV-AlzAnF9l+kr<8?kqKH+V%3|SR9o4pM2?+au zlvJs_ljEjLuHrJS!U&jr>39Ib0-Yxy6oFvuMPL+hM;iXJ#_HO{rs5u2APO?$R6MQ5 zXk%S9HzO=@;r5aFqw@PxL4y*vF`ImZM^Rc^tBFpVpf=CXRRGU z6?)8cHIM=U;z5#|x*a9u=47&pj<>EoFu5~3CgkibgETOmOE9!$v|m+~k@j1qL0v#c zX}>miyNJRU@m3i72ua$@q+wQ@7?Y4S7eNRFO*RLpQ{ALx1?gwqC8#am-N~8hLt+E( z&PvXOKH@P9D_2iYLRC116ob;e97*1!jYmleqvGMAISS8@jL(>fMs27%I8QO>6F%q) z9>x|Kt|}FWZu}P_*zx$iaTu_^GpV6-7S=G`oy=Ukp?NFIfowG%#3SdzLB#VEZdsc3 zV_?#uapNfn`IBL3@#O57YRY#qy*=5bRvte%+q>J1%Ad~>#1Ax!uyfrTsfm)hGcrx> z^oi9x8j+w}lk#B?o%8~zqeD_UR=1l9ALw)M$_h63?vv%>?%C^L50R^xuH9kHY-^hv zSeziPY&+0uwdsw{(J8b?b+;obla7bhoMbN$aEjvGP0~65OKCM~YR*b7a!RDSE$U0c z2n5%le`w$t{bR~Y5VB4?vuVSJGHR%~GNl@%Cx5BQfI2WXbfHb3h5dLz)Eh?WD@*lT z5K?9$MYL?$)08QmD(ql8BdSy5_DIN@Xlizzs)y~s@~lv#Gy+;sI7eAawR5#TN@axd zDKMudLa$X6PKi{x(&*Z=D)^T2AI$das@n?by#Q^Jh6Er(yI#wx`rVYlU)tx@h7=V3 zN#T!N!3;qlz-G4b-SW|cLI2!aCPJ@C#Zx1oIZh?Accdl+aZmg#0#X}}7JYbxFJsv) z_QK>I9%GUSBnVSVHzK;O`3xC2Qr`QiJ%m!@rZZTSQIxZKe5#;mn>>&&qndUvnzIB@ z*6S414vjRGDnqQ9YK&`JDqmU{Na}SiGE-%g?xYUOq!P0Mz7WOBV9_m(m&wr)tIH(G zt~XaM5ol}vvu!H64{@F$OmGMJ>K^>l$E*a6*uwE7j^HJ@*I(Aa7X3 z=Sq@mWl5>Ms|W5@(W`Uq1*QdNi9b;z?LOek>J}+s!x4BGKa5Ph`uaUpVYnRdNdF~+ zuP(;zW?X_kP8w8J ze#qsZB%Q56$z3C?VMqedoTvbbrC2*s;jrL+r(p=&39{niGl(4LQkUz4wAXb6dGxn6r}DL_gQr zO(Si(q!x%~kt%ycM;FO77TsUm>xvtV)cL{gEwhBc7F=ucQt9eT(f# z90DF^W$aYS)kG#|J8BeTy7ZAaROYp$6g?-|STzimu<%JDFNkr+&3Lmm0xfuf%Tq)R zXw^1n2zfwov3k*M%l4JchgNS9DdKjM4DD;^F|qF9@c<*%z$LSmO`pguj9RIFvwAMw zh57Wd)Ea8o-t=x5)glZG`3jbzknE^5IG67HguKl47{t?M#9o-@B_7>u{UhI)traQZCNMMsH=#q+ao}Zv ztK*?Y#z}V$J>`luD+vn?2L@OSC#xpqIB)K{k?h*FE5x}48bVO?>>f#pCEerO?Gp_K zVPPJCYJ^Qr>S4Kp5tcU*Wt8nG@93CMbI+^b(L+m-Fh@>;is?l{4*V{BND=RP+m zTq)t~V~G2sWJCZ8LUKb!8fMfkX}Oe`S@c+Yqx9sp>ZJE0ow>+F(!jYvgGS($2kjVey*%ykxK$G@`PsEz14Ct0~MGq=%v`s^OkE0o^HgTL|QOYF1g{*@+k;_ zT6(}$e}@dfaE@Vb+L2Pz4~OAm%o_e8w`>+#<;G1x)(j*jAh~O|gdp#%PdO&U3w+KC z5XN|WLH^#}&y==o_6?{tLWeSTV?1&XhtkQo+F^d`q5x|RSeQa^H3BpMSmbPW>2psF z4XahC98qH|Gh?JjhYc}zd~_QkI8GOH++ssF@M>d_AZ*uRLIX;ohJteXnG0(x1B&cq zgNGYA=J$N^cH=6V2YDmriBG}X>A5>v+q}qP# zj=8hqSh(J&Fr7H7Zi`ZqOFo8^EunPaG%nAC1BA3!!_aO|-|2>lm5}CV@~TPa&~2hj zX#qwLnRmLC`61FkOS#pWkI3Pw<$V~Z-4H8*0bQ9xx9RSb7w9W2Y|DhV0q% zsC+fCNl&gEp~spJ*;##*Gc9D4ZS%giAMx7s(V1=zUtNWXzP?Ra<_Acgz!^-&T{Y^z zl;DM|F&};{_9Dn+I6A}Ja;c1^97)RVOFABV)n7!h}YY3IG)J00=cAoCHOz-TU0+BlRN!HLemL*zsj~-I8 zmMP&}w|^>SV>SUc4ss7Sky$}DR4?wIN*UygEY$(IjCH)Yw;%z*jyKL++_oY8AM<6$6kmx?^k(|?me%I zHpD`hnH_fjHgVUD(2B&>&1;vkB4k1D1q~G4 zA{=p{eW*SWi`=YV#S%3=Bbd?OsS0NA+*(cYaKAF)&XX~lV)izoW)9hoVl6n0BO09!b$fuI~I_z0xiPdeFbg!})TKlB7crd7?L<8pGH0{(SFEw6`xEJ%9u<8LJ&2n9_z#)Jn z6xerQYC~{KCd?%B0v0xEJW_QlOO9k7!6hBwW506OO#%qtu- z_D1Z^t;PjJ6-a6!^3jh`JFsksvOCPN{qunq(|v2!9Mo&V3Wy<;qNV9A-5a?SwS1P; z2D>!?B#Tg7FgP?Bs4AeOy=AFa>!wN@rhZ%8YbO0k72-}jsZBjRs!=LTr3NA`Bb{Ny z#A8TnEhJ50Tx>^^xac)8;3jGKt?sx?IOUl*@aPVvT!OVbnAITBRSm&o8jzAVrt~UJ zkPMi|GJ3WYkKL3M_NIC>X-u?Q4T?e2R9E%olTfm}Mm1e&_hCr3SUC`N;nW~h#(sm{ z1rw+H=tL#v@)pynl0Is*387|3LRDwjaV)djtPlp0*AQ?5XXYXC{Xk6>sab-#t4#&& zfVzt{GXXWd6&7$_!_~~f3C|A$RAWs*%stk?)dSL=3Qh$Q z;Fz_&@gF1hL`5l?C+l8K;$1+SGJQ!8f@09cotcY0ncHf|3oSoz8C}wj{Y`>YFyYsMb5jEj_~D}xKIdWajSZeIY6S#$V9XbmXWe8lc*&LCF4{) zOpQ9}RbpLadD*4T zs0*`(@oQ5Fs&cb>O07jVfFypPFAF7ephp!CCxi%*+<+Gxb;hjRmLSb+cjAr^QdpUG||B*JQf^rLRf~(d^6H2V}@gQOmJ#nN>u!pcz$~vbxfnN_i*~>*ppP!Nyb3_C?ll%G}Rf z-!<`EscR+Su4j}n%}64Rde5F-%21qDx5!r5o_>Tgn$TCk=d}_vwMR0PtaVT%q4s0p zvb{u8fxmRfX0b;j|Avk&!D$Wsc(YZZs7{D1axJTr%K#6sIXQ<|Ux5k?BBPaq3@*o; zts%A-G%KeGLWPDf-$+DCtZyzyl4ku9d4O9^{(ASG99nMI5~E2M-u1+vdM7DCL>F$#<6r~wiRPPU*9(U)RC zTV2^9YG?=U2abb}*&U&^$cSyEr7{eXm{e60>E#(1e8(rsMDBA}wELS}MTFw5f?Z#ouDwqi)mbve9H#7eY|n4~lcBUSYAV|0=344w>Y*~W`!`qBmP7Pt2m=_9Ehu4iysW5 zX+D48wCOc5OvRAO8O63uN=>944PEsln5Y2Eh+U4mN+)Me75e(`zxKKt&YV4UN~t!M z?d3l}FvuNw!a}iScX?<$BM!EWFZk0jtQpoIb!WrC_L38po81U)j`JSg%{x^t$DN9Rni+y9P!FDrI$pr~)-L zg~>yOEELuD6$nIe?@+(_J=~wEh6++Oq2zWN0qOw?jXYSw|G14_^Q?G?p*!&1 zHBhMxR0f6zb`0#)_~N1LqTW6kh|xWL+6(xc7qud9r5&^z?Rnm+CgBpVP8>OK)5P?# z>51o`ICA3fi9-jD?K^(-_5=IeH8z(OD-eT2N`oN`sBKewD?`>`pJIK5Da@=xYLFXb zZSwX(54?^Qrutch4J&fdaM%5@va+($4ZpJ09hGc%)N0-PafelKBwO(2o9%+cS!KqC z6nc{7n$3<}!;I-zw=!3ZQ?Z(v2-Z%b8} zv308wWUCeFMYEHvUxz8s(@w{^T$DERI-%IHa3akVu#S0&xVc%$y4)p|p16UXg@QP8 zt>Bnw5z5>k#IDdh)I6S=lQphGu-8?}2;L2r+$~trUQ|asiB_0aBy-|f(A+|dDSN@% z2vq^q3j&#@cY3^17L!qjtyV>)l8c3tvM%df7WRd$kQ~q^GUqfb%-Q+l+G#zO%8)=` zHk5ip5?8kCS~hG3bZVL<(Vo&t(QStyena8%*OkM}@K{wj6PyB+a86AjYhS^v(o}cQxi!3`8Bh+uoX%8ghAf{V!E|%KZzJiq_ zet-F9Qrsh19imoN)G3;&hgHTOCIdkSPC?fUgebMDGlavvtUsM2UQB6G zxh#f)lDqKJD8ZV&K%yMZBJ5I(C3N;QdnuT5fpw8#T@yB zDSH*+)O~74tFmH?B%l~>-GqDYB1nj-sm0^XRz21OKx+}%8A44i$D6H#6m+%b$BXui z8aKjZJRxA%sh2;cR3~<_Om_#xj8aJ{+cJ}YOp}ACOuH3g5`u_Jm9qEA^`;|jzY1i0 z9MFipxdyKdFdlewjqI^cQ6VL9Ch8=5;-TK{rjZE7Gkj&L-xqO@T=YOC7S@R*0wHU& zR7_qj;VJCdtjpfGKoMai^2tmficRly5fQ;)UsMaX)E-h2CSIf1+*Ot-rZ?RK; zyVS^&`vH(VWd;M|xawrPYMHyB#6m{xJ7=$nF6t_s!N4RO>}f=(;=oLDMT!$mg3X17 zL@6H3_Lmgs)N0aQI)%AtlA@hqL(!71VtwLH5}AU{DsUZCt8JyNQpkS&7vlD)i*ctW zkE9A;zsADy4q901ylTS#zZ>sLw@_WMm{HGW5(?3fquz^2O%^*Ch4P+{JX4~~bcdgs zi?uybK}zl8kjiC4H?l?dv_MXdhb{^Aq5PJP^jqHJr{|~v5=z72%~Op zdBw~Sk)7sSy^$o#ma*H1dAOv}05Q~zKu~1XY*B1f#^Rn@xdYT{cvV60*?wfF*Rr(U zgT`1>bh5W#L_Sn(6!Vl4lw|-K&^g^N6`d^q5M5Mf2x;&Da|Z{d=%bd3*Y-U>iupte zvNLzkWwX`-OVdTlRg$VHunJR4{8lu5C~$deUD|%7Twds!X<@07jY&~5=LD7RMIq3{*fD~fLG`M{LWn~9T4W)R=xlU)?2G3#t&ZM5fVo0#YkAAedui=W4(-xEgLL5aPb;vc6N4m z(C*B5W_BgnI0W({N5Hw{5)vT6aDnhU+z|)|34sfLIDR063*m8)gM+~RmjHhfo<~A{ zknXGM?wOw1l`RanA86P8tgfoAuCA`Gt_4NV)5q&E&@zygzRA@W#mP$bJj5dH4^k0# zxW5t0qZ(9Qftq$aB@mVw5aWPxc{PC1%w7Rw3z6^UUZX61jLZjuQju#75XhQMG3@v}XY>u)zLMIBS}TAX?k<1U`v7S*yczZVm_ z`b}96kq?^^SXjh8$&5QreE9~BNUNnL6=;knAhLWPoOI)(Qc-@ZDJn(j^;voxE1uZ0 zeS`1)c&gN-xDxnFyOLvRDmYbp*Q1o8?oKw(aLd+59E8-Dn9nsukALBsO{$qF!UzSZ z5vD|dKwK;_R-VzbfpR*A%9RomNpzo}$0#g|DUK|Sv2tyV3IqV}2ptG;TjJ?WGz&bs zqAlJlOk5tX2SL0?itg5IGukUfk@MjPFh6|TYBaFrn_X|Q^->e`)(XGi7PA)tg31@( zJ(YmEfv#BIV!&KITDTt*+ZT=SlfJ9 zH``f_*`Gs54V7X1Zn_YAi_wowFc2i+(w+)Ou@-EbUqS|CApr7f)*ZWiKVvrss~PH& zV)iUEGl;J(H^t~T`0BC= z%Dy-rX#oUUM9O++t!_Im>%|9z4eMY8VgrX*n!>#DG(!I%WCq0Xh2$`C#4*ETUQ&_B zhg+?g1Cz0BZ%v#+_)ebFSi4bCdk>*EtN~Kw^k=h&kJ)~7_7Nrr*R>CcS!Of?98j$A zm5YJJ>|kJFIv88>smNBznTyJ+!J5@9#rm`KkxE?ssOxGnQS#4%PzD{kojz=7MuH;h zMJC20NbT@3P3s>Hra2F<&$b)}8+$Lmg=UB+8sycn_1R{?2L&-m&Dqdpy|-7Hi6)GZ ztB{K3!?Hz(B^+;ZCOVjCIJm^*NIMLS1=lb>U26(Qacd@y@sL<+4zFUNPT^b^6a}h$ z>P7EuTUdj6X2PKi%Id;Y^S5|x39E9ZVko5-2LkGE&E0B0kKYC7KUucpVr}4AP0-K9 z-z%}p0AZO$VU2mqHE#*1oX z=2Eppk4&L$G*GFNNoo+ktSCoWj9121nfM1DU2nLWT~Q!rFK5}fl;RiJ z=;{R-=tRkj&_!n-Oi_UnDD31KzEVw-uy$L z1o&h+06t{CvE%N9B02=*v)M44fxto=c&B*AamIux_zIbNkSS}ZS z%-q2o0%p^)KYN5jd^VM<=e6T1Hu&3@aC*VCG7VL{1RJs|`8;#F$5hQy6z?pCb2wFISt+>fjWFz^7DUsNq=B+o1sGl4|IJCqebDj zy71`Qvt%>O@Dnr2Oe`_rzseJ7U(WD^Yb&%gm5wZ3YGT@TRLLl6*@^Z=(`ysyp0(-z zu5>@UWGjL7N3lyXUIKw4!>M%l+VntzJ1xOEjX93bpR?@#!E|?5D7$P4nVnvysuVRN ztJr?uJ#Fdk4k6#p%HWJzxVFJboY>#nbU2}&+BPV_xr=l6-~>U zl)+(4D3VGK_*BSi6idUYbWeY}#~)Pzdgajeh^-d%d_k_5MOVpdvZLoYeR}%S{r;Hn zDPrBo%bHQqil!w3*_Q72(E=WBb_pYdvF^It(*r&rMa9l*vS~vIC0W&NwJ0{VHr?;D z3@vJF+3Irb>4A0+XCRaWgtVu7e7*wtD#Ke*vTlsYmWDu4{_SZ`cdzvt0hc$Sk+yV? zPn43G0p_v_rXd2`mLBjC!~6{eF+M&2ilT_cd&iV#zg)d|7C|r#k?O zrPyOdO&EnhdB@T;wIFAdV$n23Jg3tA!f0HNL;Hu)JwCOWn^u?wg#rcL)!?b%%A`!+ zND`;mAP5Ao1MF?#K~AVlW9umuY9mTs$6KU${NwLfP;TK_6kb`|A+^I@)PVhT6b^Ni zBEOv?GP;~-mlH{We*Niz0T0(TI6hpVdnn!Q6Q@>%WI}EedgvY&MO%2H)M&mZ6=nCF z#VuPC3kL(M8ePo}vKI>Y(ZOyABgy!W_o6-nTQ#Og;R*%&G+}$ev>JBnoo*pn8fevg z)dIjMy5R*I)=&(I*9^D7*xDpO4a@5A+Vns-%xNHba48MPyYUv&8j6GiK2EHM!177c z0;_T$zm_vfV3`+N1{<7jz~V><>66?|D#b4!p_R{bR)bMPz~LzP90Bh$E@uaHLTmv| zQ40)yP=3%L?Z5bl=s<0(mQNVNc3|8*QQASxu^fKysE0x(&|#aQPo#!Ss$ucs2nUAs z517btGziZ&yEtrM5HpWrbRzRZMZxWb(n2su@WVQPd(ZoQANR7;M%tDd)6wPW*eNSc zZE8MkWy`AG)B9GRv1WTZz2p2(?YVI8r@79~6sK~=k@iT@Qxg4fN_k3R2)|MZ`jw<# zDf-n$zuM_n2mR`#U*0N)pXe#6Zkpahzi8{J0s5~&{A#0#Z8WisB~k#|hG`LR&122B zQ@}cCoeo;3gVyPwbvkL0E?T6E7U`lzx`sW;@;`J}ouZW=8hZ{ea75+sTkA;t>eB^Y ziQ2OKSUO>~m2fsxRz6SUrAQo!vq=C?PS zN^FExn5)y=zG+axf6aup}4?7H3n=)nBdr|>V-pWA{U0Jn@+@Wwewur=JZ&U|j^u+uexLSkqHQMZvqbUmSQS_lc<&|va z{x@RVjEuD!r&+a|#}}MSSfY;^jA=i#61Nxcpp1hwr|ikE+&9sym>Ag;Zl}P(39>ai zGr`|1st*$|F?#8kU$IA#AZRsob@7i%1P@~NKq7=9X17;aoP+93J~oKNrb3)T&97Zc zOpg8830*NS6neWN;|XfdHZG17QxE_H378Ipo6~d%c%PtQ!b}jBJq4#a&U%4 zl+wcRw!F`~O74w&^k+dvHh4Vi{;y=Z2f1|$>Pdx7gNKL4ao z@VB8HFhZ4!n!R`-u8bpD#C-~0O%#S}wdtsZyTH~)rMn^TbY}J}(V11@U z!B8no&{w%8GBB&W6XE@@QO)%*1$Vw+t1Ng1`UByOK)4EwPElQ(KX}I9JH>!+fRMfz z#|*j`;l{oXf0n^a2X<3t25=@FS1ZLm)S@|H#-6B~DDTdf(LkBxQDKX9wtILcB6dG&`G|YK1oUI_DX4{$On^=;Q&1z zyA4+~dr}%wCh4A3T5H!)Fpu*dnP&!KWs>KVd_fwn~==27evqe*~G|D2Zu2lH(6#=*XA=GEJ$^aNWF%J)h_(foL%9GV9gJqk)+l3`WBnL`C1}(zh zDPr0DpP<;iPshMsy1-P|!T`nW?G+l*n1^THF0H!2%%I=F4*nL)atSPtEHatL17XYJ^D3mj&O32PWi%XQ)^O4=)CQfI?KhaEY=?qTor6 zQ;^2ANgBz5+Lz(ql2V2Tpj=%=_b+H*(6lCPJzsF8Cbd~gB@!KSDv|1xJ^_!yNT=i5 zFl+b=F{>9ZTn?409wTny*VOyET9Z9kiisvRDY%X@`*|M{2p)Y=?VFuI0MG6)d-%e_ zGo642KcmzzZJ#mlC8L@mgl@J`gaj^PQ}WDDs+Quw1C@#+IT%%m$*MpDY?M_e)r?FK{-V~Ng|08~PLYtyuYqw$Ygzs% znQHD|SmJE#(Sm7%Hc0g@8kz`TM*UBC^*)B6hO|QQ9GxrN7$cRvRV*oXz6=||Ca1YY zvgng)fK)nXjI304G~3_a0QZ$`!(-~;*$~%fp-z)-D(vT-2kHizoG%8Xl!DU zOXSrFFugfWLDsUVj*esxjV($$6>@Dy3BI1|Z&d@N8691R*ynK30bkj^Qnmx$|0!q_l0V>N zbJ(&2uT#Kd44G24gIZrh9l>&)&TwZWftR;SlwAOSAh$)n0X|}US|keZN8v=`L-Oc7U2rwgTR+aRGtp@ zsv+v{%;dueN7X*C%q!wqdq5cg_C16`;Bk1s?~^i-pcKHzFA-J@xVJE^#@2mkc^JZ; z2Yq*Io>^B1Lklz&7!=JBgsMM<{)e>$JYvB8&HL3A5JZZM5V*)0e4A3+W{4^bl9Dct z9?3qKl7JB^U9*^*!NSkwkr(2^Gr-a*%-om5I)?K;lnl?P?stfJn*D2Ps+L9sFmndY6=G1Iw+A!dJo z9=R79Op2ISfUTbxZX$rZ<-tP)YLaKVzu@`59l~kajz;U2wNV!?Uj`K;d36-l3Ajc_ zHFBJt@L|R~M$Y#GEIUB*JHj`^LOPDP90hcN52#QgD!pfCLF?f1Y}P{hgW62MSRuc! z4gL{?5UT0RMKiA(gnj1IbXT=_N&}>nGEPCUHHRnG(?lR-FpX)cF+xa$5b`bfLkO8e z2)PFS5JKt*A=k6?r{+PKk z%S9rYOx6+7I1h~$5kisxSK>H;WdT5LI|{%T0nj56a^03|V$s*Ou4-&`m5<%?t0!)l z_?Wyz9slRg{mru{|KnvR&1>BE)$gAF**{-#?@RwHef?SIJb%=uS1ca*`ddq%ZrqbU z@P(F7uK4!W-diuZGB-c+n>$}W@}>Ai-~8Kc8*kis>sjM3Sjh+KuYUEh2mbDYFaGfP zJG#I6#CdnupZAk*e(!JYySt=6e_Gdf{%ei&ndWQPJ@WXKmmmGJ%g0+j|ED|l?XBy6 z`oF$>Ok4Ed9%vbvKP4F(Zngh#p#AuBZb@}E-SW+Bb7%X??{7~O^q)R=#lsJ7-1OqH zm*u{tY@Bo9>-z^9F5O2~T=vPof9K}0w?6g58}^=a*17YejiaJ)dG~1^Q@JtnL=0wQr z?;S9{cGt@L-&=o0?8&dy|L%*?y_yA#_rpPl6x-t^}Da%xaQ;^ zy?w|2ZJ%oU_2vKjg8%&4f!~<@f7$WJ=a$`=z55@Azxn4!)*N~D?pL1wT|74b*S8$M z`?l+DTfFJzE#LU+JDsT$>oTbeEB9Xa;@^L|asJ(R?9QL}#-h`1>;2c;%lG|b|MrW1 zdii5ty6TR%Z{1q%ee*YWKlW7X!ykJy`DpzmJ&WeOcGte*Y5(@JzN@bH`Y&&I;(|u~ z;T>lM_2uF>#Mu3 z*m14;bK;Ln~#5ZL(4;_+_U7bds-e*6CZtAer@;9j$JchKk&?7J#^>M`~Lmr ztzQ{EaQQz!-#xZjKd}E>188EZaE8e(s_un0R%V*A&p1Ho3(3tD-W}V2JoyC5&b96M0g8csV|Y z&Llmq`O=FoR-V3RNAr@UyJGpK{mWnYLd)^zzy1Sd^?yG2tM9$>fA(B;@ekXcd%Nq- z)4!}QdGV=U;L4 zFXVrJvTn&2Z<$+v<727s{n7gWH=RAMrF+hMwsO_|1C{e-x$cp-dw=(xXPWL>asTAA z=JIXh_g%1{a`aO#|I-=Q-nk+6@kei&ciM%~#<3S(`stkS-m~*R*8JZ+uWj0YQ%~1> z8+w1-oPF;n51sRqORoRMJI`NK7)hRR%Rk5i*Q~qna|a%4`12Vr%~^W#GFT#quQUI)7IvRv>O zcD-uH^E_RZ^O~XAifh`T`q7$YAkeAi%C1(jii+#6dn;;|ww3W2Yj79>AULkADJ2ii z<7&1FhAXd#hXGxc*+DtS04(KYCsTzqSfgQqjw^}+W#E$(zLR7mHII->=}HZPb}p>B zb#PWOpOECTWpd}DdGBr7A3y5FukX_rz2Y^f<~;O6wMvP#in_vhQB@R0C<0U+*KMr` zu_%gq-qSV24974{PvwA)#*3;xF0=x49v>f%JEl73#DhElD$4kHO4dq3g`pNF)-OL&$#QAs96s-aIk|@J|DT3o=E=YE@hW?np9{ijb*#Xn7t}@`$0i zaYNJdg-#AHa6P0tW4f9xzy|y4vg64m02S!DGgEe5ziH?!m;%Eex13Np z7``*sWG*mK-c>Tv~g)2E^45$0E&P~ zjwP^ul7`)|7%x~vNW;=&2&vy3A%rhoOJEsY41YcXf0h!`7>UE~qRw?j7QnY+m*#_2 zp{N_>iFzmmmIvsgF`6~iG0kq(&G@8Qw#~7)YuYwlrB|V1=^jZ);|XOalLVcH4$+Cb zjy$5cwtn96gfzyoYI`!*-qj&%-AY1kPj+PGOe&F*+uOR5o$Vc6ZJmiWSYeOcYTEWF zYSgTH&9!y`Vw!gbPOwgbE%?0*<$$9z*l)nq8uoiGA*7A{{sSSTmoDQCu+TTm0mqg_ zano|+t`jesdGKjjv~_gn#?5E$JiCAEI)D+dhEScss?LF`bx?H)uS%6WsC~rN(Vc^v zH?6I%zJ^t=gX(k9rG{4r6vL?)?|$p%En9XDt=|&pzKzwN%jpbF%glq^P?qRT0g~9(hA&tkzkuw-d`M?0G zx$qA}B*z3rBs3+`09siVXr*Z8aact&kM%bSm_%g_nh4PXS~)t<3Z)S?q~@?8plp>| z7sMH@#21Poh8y@EA|t7`2#KU3q>&`yPXhkLBc!n&QQ(%W)(B}_3b%!vRq=Sfpu)70 zBS;qfFiGWVCAl!p4UlIt`2ZZfj{OG0MA`3K>j*hBGLl+I$o>dfN-|{!#u-l}lJGz1 z@Jm5P%=gTZi>OXMy%>@KgKLv=LTXaW$aTd@$tuFWA}dX-8(c4~GaYb9HC%`irP(c# zWt$Z}t2t7rr)I$AhtyO9A&v7B6NyA31@dTqVj`LC%z&_(C#6~wiFqKl+Pf1Vr zR9!Bp+15lWtmPoKj;RIu9LU%RGEVAf?QCt6c*O{`mXs6gYN9b!8;x_S(U|&xXvCf< z8b6$-d^EOIp|Opjac)N<@nPaIB`2aa@d)gg^4Jm9tGX%_u1?CyTAVm&mv?Knv{q3y zcSa6OA?iM06AWb?9bKIaWr?otBqW$ySSo8;AF6 zcyUl`)RJA5hBgO17uY`79dS@`bR!?vDwe0QLDQf?8(GUXCnmj}EaCd6P5|GqfG;Lfk-2zQGF1=x5keX^1H~4{ng%zn zAKtWe=ScrxGp;ir-xku~7CTFd3esA)98HZ|j<@-udgVAS6nvSuj{yhY_u*PKeJLC$ zO2N2VhS$aMV@GDQ}V>H4YZ2J%rd-4IzurW@wWC({jck0#Tw UgJqxT>4hKvcxEA)X2(wd4X%IxkN^Mx literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302184004-Config.rsc b/MikroMaster/20260302/20260302184004-Config.rsc new file mode 100644 index 0000000..e7fd33d --- /dev/null +++ b/MikroMaster/20260302/20260302184004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 18:40:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302190003-Binary.backup b/MikroMaster/20260302/20260302190003-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..c4da39ccf3ad783947ebb8d89ce8573240193516 GIT binary patch literal 289700 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�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�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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302190003-Config.rsc b/MikroMaster/20260302/20260302190003-Config.rsc new file mode 100644 index 0000000..fb184f8 --- /dev/null +++ b/MikroMaster/20260302/20260302190003-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 19:00:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302192004-Binary.backup b/MikroMaster/20260302/20260302192004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..b89f80ea4cd4da9927fcca76ac2a4359bf084e56 GIT binary patch literal 289700 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302202004-Config.rsc b/MikroMaster/20260302/20260302202004-Config.rsc new file mode 100644 index 0000000..56a431e --- /dev/null +++ b/MikroMaster/20260302/20260302202004-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 20:20:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302204004-Binary.backup b/MikroMaster/20260302/20260302204004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..c1fc58bec379f0f69c3d666a1cea67fc6658499d GIT binary patch literal 289700 zcmeFa2Uru`voL;AfFyt*ARxXX%`UK;o`?kz5D`Sch6PhL5GlbVG#i4VSg~P6#g1ab z-o=8wcSS+5V(*Ft{?BX@#P0iDfA`-1_qh+x?#Z%ecV^DaoS8YZJ6Wq17A}dQBV&Y+ zG9f{wiZw$BQ4m5ckZyxx3lzjQMJS7kSdNY}SdNZ|DX5A`F++%nn5fDbu@G{m%cErp zG=z{kLF0uGf~L9tCiGfuqgrivtl=7yT5WH#9mHm#DhfP`W?t(Dz4i~I+CPkI|1bee zWO0&sr9vVjWQr&QW=-@!!LbPnVwgs9|JpeN~Rwj{= z)TyejuC~$N1CBN*h)qFN3^;Fus`T9uQmf)r@d+xm*6?6l-wBR53S!d{$^-m=@^~6T zOgRYykS$8BN=(4?1H{$e4M6AV+dy-}Q=kK1fBrN=h^t4Hju6ENMvlajiV!2d$_RQg zCR3=o;iSNDstJjl_q{$;=<`J1$Fg=Gqhz&GO8{zs)E5t;L8q!}6L^rGX~?H25@Tce zx(+0l)Ieqg9j?hpK4Q4!*6L#{mB?Ze6JSs@ggP!tJwT78yZ%_4eStbr`t!hrhBow$ z)Sm~=^Vhc-2%$KAn~4xg)wc_&2)UymwlPBa2-pPB)6o!~!L%ds0+fukL~J~v1)2HI z#XxXoy_$<@3T;A^{z?k6A~^{$SdNZxQ{W^6SHk1S-wb#x3n8YBDMC!+x&|o7Q7H=0 z(F<+>u+Wl|lPysddHk)%0F8e77&^eUhVj*7G@5AgF&a&DWDVYWdD0Pz99I(n_D2X9 z!<|h#k#`2dB4?B2>7?2Vn6azXBAtr@Dh`}&HNC7{hV5fpz z0_+BYYQfnYE(l|yhEN;S*)07NKw#7LZBS=Z^li9)s=n<-MQ9cZVq22J_zyx97l`bDm{fzhW70sMT5D1@S|ZL#PADXav05hp#Tg;oxz4ocM*AZ= z%-B-zZQ@c{ueR&l6{(G8HhAKfba40KHU%!o2_f84YwPBEXUB!Spz5Zgenxjlb~Td7 zuVRt_pymiM zikdQEme(mW(9=u`IpdJfw0c`?X|k-BINCIHpc`@hEOzU`UAyVihAI}Ccq`qaDs<2! zeM+3{uxeqr-I$!lW~bB+01ZQ@rU~`b?*a4`ML^M$qXYnr=xRj*L{9ynaF|A)0ZJY5 zdf$qTEj=#`C>Zn@J;TaI?duv+?&UDhV{@@dOYt=dIX>ZI43z;Rl>Ib z5Hn60qgF*qB{9I^2D$iMsetQZ33;Set&EBy)HVHJl7J14Occbn0?Wt(W)X=@OT@Zs z2(4BbA4Ogd8{EfmG}9RYjJgO>O>4m<`+Y+L<}S5L6Q`0BaA%nMa`jJuV=f9}8zGc$ zgltg|+XNxfut5lsstXJp!<>VVIjJqHtE)}Eyp~OB=IZKdW5cx!1+F`%z>N*p>UAYp zEQ~YngmPeZBML&z?MXQ$C7}^1sU)Y>WqQ>?2uY)4s(6KG6cJCTC8Tu)+dw@Aa2%+c z6G?3YCJjv7fHYWYKy%PQKs!r>C{_p|3%I{ILX7v-K#nSMdM1C6ldc^?&M*efh@4gQ z;!m;{&@Wo0)g-92o^cXoykVri9^oShG0kCw4Hs+FNeOC|!f^cxJ@jx~fr8j`5TYa@ zgeD?{CLu%_2M}h%ZZbkl>u6|AhuuuQ-kb$8(2b&lem49^4QF1_&|sMIN5Yv=u*-zq z7}$*mj7B5mY_5ovXrev!piP6*Q(-p+c4J|e1-n$()uupgw-n)zJ$%1OGV#BRcC?$rf6qv7%?C+JuBj#lRI; z^wfak6}^RQurrMG&W0m^MtW5Mh;IBzuC*umTesQPYTMOn*Q?cbuGMy`)oxU)4Lt8E zQzgc03AM&a5-)d(RmLf`8YhKH?W9#JC9&kBs4)i&O%cLD@^k{|470QjZF4=^?qm-T z>9~Ygji*8xt0iF6ewUBH3#`>sCw;%efMDa09hHh&KAx)%R`Teor*>`MPNx-alO{uz zGwFjW6EuX(6BKE!`?S*E2ac`u_W^A~8WSXC!1X01$xKZQN+dK|cU63BDiA_dm)56 zq9C@xY9rk!avT}}P~akfQX#otZ^!FKi-|rv*HzBn^SVJ)zknl>beI7;uqx~8p@Cz4 zJ?VfX)Y=62jEY90j8~}OH*7w&jy|6miUgku;Ew>J3juu6(j@&i&~>EzlJiS#E%AAj zK}SS>Z6vhTKMjtpbrT?o0!)BFFeW@_1VcZr;0VHKl768x%vX9f1v3{!Wjy7HO1S|O z7#!H(Xs^4sGyKL`h=wSgvLgm8WC3_&M_H_rh}TA{60}NHyv7Y7^s2hLx~=XG=yi2< zwNT%FQ(axn*0=K!LTx`&m;rr&@7jRcu)^ZA!y`L(59rt&2EbhRD5X3S zfECv24Ns}*T^CEi@S5I1-ace!hM_aNRzHBq!0pbaZp}J%4GRzU4)WFYh*oK|@sc$ zGmB(7I!ft=U*!L2hCbb3765$#Q>i6FFxMa$0H)p*hY5i}GAab6YR3k?5D120*qJ@M zh6ehFcI_TgmmJ=j$P|+bx2}zBEFsYlHWb}+U+VD#`FNpke?SPm(YM)DgevrH9u=WV zeVb4He7%5*&|Cfa)>MRE>)Y*Woeu~16%18`PDCAi5bS${eOqHL78k*Q#qto%pU2h2XoR0#5s7M}+EtRQe}g2Dn5KF`syzzeys zn+rQq{S1ZH5QLnqaWPjY7AnL%iC9R82|_Fp%As$k?1)KE@?ZQ>lw*F5a{X^m9)yZz zzeKqQIJ!Im_PZ!s;bH|QmJ?zHE*9Zpxfmx%jGvW0pJML#=8s|=_H&Fse1ma$iCpRq`*e#>7HQED(qZnV8EF3;870XhiZOpV1Y1tf{0517-IoSlsVx z?3ok;e=|UVe1m=IBiS#pX9kA^;NC)^u;cHdj&z7RnmS}nto) z9AlX4zQMSAMFaV-#+en~HLO!W2XCj}$J>g;TPT*{Vj(W(iNrjG4sFKX^xl!L|0vp> zevURw>))WQ9Wv^dQfv~W4AUxQG5>C?IYKe65X;$OoCPZR6CYJMbXcv}MoW8)I{7H*M^>ehrRQm?)^b5Uy ziFN~jNvtF#)!mzoxhJS%-3P0ZBw8X?;_e;)Z>BE=A!dttY_XIOa};7+H+@x6LwC2c z{q#q9zVFZJ0A}hpbZEKj$uC9SqN8tEV0hOMcOEws^Y8fE28%T=mUG2?Is7T)VuB~; ziby6n9~bxOPQahFSo-}Od9cgBLB4N6^e+XT5lYD8l7*R60d zCT0u7I1g+Ykw7fb2{>w6&wJ*I+j{Lr`D2E8(0A-sCbhx7l)RC(0}GLWJS?>{-XCA8v_y!>f{~>|S`vgqRJ!;>B*Yf>msul- zEi5{^^fQ+)rXX@j>2qv>5ftVZ?!@!JAjZJ#;oY%on0s({ACd}LYpxFvg+q|R8W#(N zVhJIZ%f)<5%n^xs+@Hi9zPXlEb-LUA5yCLPB8;?#FbDO7Vb%}^VnceuNP#ffdcwrl zCXDJAgdvyQ-D8P(k}!w+BwaqfM^6};P|TBx1$?nw2>M;B_z7XYxt1i1?soV7sHHRD z=W+r;vTx+XqG;5sti}(`{{!)zWR?yL~5aTAN`@ zgVZk_7J%FuD@p6^N203#H#wxbPT#B_kjn_L*a9Kw0(~qQjs+-)ty{RZMTlaD5V`)_ zK$pElE?hh5av30fgj~ymb#hqgVZd6RF5MOutYL*fpTA?R4@N=wm|_p7>%;Z1>J1qe zOw>?+0W5vfT*y^#-P#n((Xm@SU2qsVv*IKgEurq%$tQ%26@QHsBxxwg1X|b}^+>_d z5e2a!O$*YqEG-bZzQ|}rAy-eBWMW3GbtIq)B%fT;-vEx6$ebC-Er#_PSnH{WP(B5j zpdhv_VBkmUT{^svg$qyhI&O=*7)Rt%~7h}=6R%ywd@R5GDxAVQ2jMZ2i6 zke6cBl?=2qVss~I(Yo$ufM`G}GIfjzOXf^i6k}9X1D&gMS(`L+nTpUx6KdSa-Kl## zp>+fTl9KYsx@1Pi0PC7)JFK+CDCII$yjHD>^^_AyN*SR?n_R||#i|l(*5vx?{{zRq zCtSK-lS^BYDsXt}_mND_{rdACME_4BYOFM#3%~c4Pub0<>WL zFfk!MAEmX#=5P8bTBpsl95&Hh4W;(Hi;z*A;jx&{U@LxGmNnUA#Jp@XrSh*N2aye~%slpVz!RRJ%P+WTMeLruaDy&ez% zID>A01#*n2<}4sf9n#)xPwqX`i9cW$BO*?sj0GN+5$d?fdOij@gAL?CUQgF`~+l0r@y-AW*Qf=_D86d`!k=%h__A%okI}M`@!8Qq6kA6I#gN zF+&J)5J5Fkj1gk2t8At;L5Q(7Z-H_mLX2k*ZP&vj0ul@}s#hXH%-%x~Vi+M*)EIOy z%m&n!(8@%Jkw>ZqeG(o8<_Fs@gjVB3=-|Z#d@ftW=kah0gs^=2$WP|eV_%u&k3X%% zt9s^Ul~uW(mZiG{TFRduHKsW1-YcOTUmN~%b^VqVU2Ph+7iCoRIBAxBX)4MsJmk1% z^>N~PtIS(|mJ}aX=d12dCS~+nd$&WP;^MPC9xq*s&)!hYE0SKDeQ3l*pR)e%WY*GY zmZ!OOKE}!Y%yO%{7aeI3J+t$Ytv>#IwR?{XXVvZ8&!o?(=)b)FrR^0i^d;vz+wX2a ztxwF$>*?<*d>p&&_=jp68&TYi-OEubYt(jjqlKC# z3Y1eeTI=aP$uwf(^p69&TCB4VaCNMl(_?D2=51PsY{wh-hn}0d(U;{O(BaZVeva~j zS$^c&MV$rPw2Ke)h?`JGy?tuv$Z%TrtR?YNkFL|KZFqzcT6#BgCVxkc?D8CowVMOZ z3~SZ)ibKNm0X<9ksmrD|=)1`3tnfkq+7vr_y{PbS+ zB_FMa)4L6Ky>4b_>PR_vbEm_>>*4*Lb{l$m=E1tG>AUK^w4R=aF|SngNjUgPhF$E6 z?N6s~U;pY-szNr`Yqn!^6y*jbAed&8U9~@Xd>_H^Vz8`E`20lXj9k-xvGsTaIoQHpaEx zh-T&qS8ZQuu3m_8yfOwKWn2*2rk({6HkXNKvzAg%?eFTAq|I0`^xndkd%Fzw`zLH$ z)2olyzD?Wk;=-D{ON%#To?9wjXVE5y`@-uT7)~4Teb5WM>INP-0@7qi|)^)=d|LCI`ENA zw9}b1&4QA}aVebPWy7bXNMCi(mYCdQZM-ZmX}GZ9@nO~e0x>Ok_KgAj(h!GGqlgy% z69x`kHa@b@zG1kn>B!VpaoJ6_Z1Rolbm{51WoPE3EVPf9-tWHW{FFwig^@Dl*i*6Z zndL)n>^s+1)@{h4J5q;ho8P!jYUQzYYpT2cmpUHHpt#fqieiLl859eIWl&hu3(Z`FO>p8w;59K`G18pdmY^IZ$lx89Td-_IzG8zdU{(< z`Q&!} z!fxo;S>ENP%lF>TtNW_a^B|8QBTWS+-1q#$z9Z&erXM4gKg*AsO{Gx~WpM_Tjb%_h zusX)H?hP#{lxjMiMm5UA8p7|!bQm{AOJjR2V&qEGjjo@Nex;{=$8d3co+M%j%T2@2^#uojHqf z40onb=uNT4n5*G8MjdUZPYPG#Y!9VJEX<}JDs_}6))MYom+pqSWc->Ltl?rOx*5j8 z7{1Grv1@nZHjp)s=CYW2EOP`7QTdUH$T_bsZ%Ev5Hd657&d+i9wk>rvxr^rJ(k zj$A+J(rlk|lZ>+;zwU5l<++7*+u0{)-MxX5(J|rMdSi!Ny1)BA)! zOKFt3?wHMfn_l6Fuu+X-GZ)wE6DQ`YRCl_sh%5M|f>5Y#+41YsyZB&FYY44g1hD$Lyqc2}=s-@H!>4 zN15%i1=b_Uctlc`EnlTaoi|u*=#0OQY?JPDoo`4Y_2ysza7FO%Y$8 zetYY*Ph%0X1ltj8+AM@D!JdS6`d|I|SAYK1pMUk|U;X)0{h9sOEB@;h|MiOhdd2_0 z@QNoOJ&<72#H!2?c@(%oUwqgYd~12 zzf-76rFH6sL;Mxqht$2zu8*j~+6ZIBqh|y}RI5i%kAaA4!GWZewIix+5)oqf(Gk3e z!jSxKP_=RGpsJG+z>Op1N{N=hBfp5T;t+(#SP;4}#xkf+bfJs7XrC23Fk!{UDTA)H ze_Ni}#Oo_(2J8A|U7*F%Hhb$PJo9xtb{hx2DXx{qfswVr4?+r#k$rCXaW zcbdgByW=aDy7W`OayQu*)ZVL%;<_zG@Y;c3bMKBGG>`st6r;~Bs>AGu%P44$W^!Ei zB9pw+GtXW1m8A39*i;@UiX3>&bcVya1-Du}*wy0VtV44L6|~k`c$KUlusb3!*uJ8q zg{JRV2{FIwvDdO=!K&NyE0N!Z>iR(~WE&gVn{um9qz z`z2`M*;lvf2fcVQ_)XLKcTVKGFM5%dYq$ETwLo-c~O>##$wHx+Z^F}C6U6biiw=7zZ#eq+?pw)&_;3jSq) zJu_M}s@>R=Twa6b$J`ixIaA9lzoH z+10&*r#(3qsWQg{I&DADZh_Sir#5v*nPhH!_d@8pY7lCFFKwb9H)CM%sT*}b4xy?P9@4L?Tdjlj}vTQ?uF-OX3F z8yy{}O}8E!Qao@lbyabvrFDk&liWUWMv<3z$f*DQv72P|U3Y|Rocw5CqM&W!vIZj? zH$%?BMd!rFavv0Bzl~he&DPIyE!Fr*(dM4#%~wshd@1kcnE3tW$0~x)FC6+QsWpTs zKp7iC6ri9DA&S3x@~@u!A_n|dPyW@D|Bvd)Y{*w4Eqt7VD`bQ~Amm~=UnmkucoGa_ zV;qTyP{@Rs0v8fesa(M02{8dKAmlQf$K&vXn23W3IebD!TKM0y7)T5MdzJ!N_)ao5 z&gQVWQUN9rNx33ifXiiEOd%lHLLQsXk%4s&3uY=viTYwe4bm2=-NV9|I?JA}&z`7* zy0+=4j8gg#YOPa1yv!PP?cN4Hvm;kVDP@FO3t!T40MowaD*srOR1&MR@_oF&u<{Lg z6Y!BmGF=p`eY7{s7p(meg}t@4t^Au{@69sZ}gbl!LM*(;=m)lryS~B+X6B&LYU-B zyIyasv#iYw4+O&C^)WkGU^KP1{F*$t6XvK}d$gHBs#KYlF)ITp!FlGKVm%DK%Z5$>IJXUpL zgN@woP@m@W*?V3*d4JBd!})?O-t4Pp=byeyzp!IsuXdXn+z)8BDB&tjzy5Z;?Tap~ zV3YjEo!j)^l(u;C{z=yuC=O3D-GfGIMZc^;@RTz1`YPl zT;JwQ_b+Vz?_N-AMchcgNOmk&u(Ff273=-=j=5b!*S#uRLw}u`%2@1X|1q%Ts3P}m z7Y1?iC84~);-B5qR#eL_+%_3-Zt|*Kw+tO9{>zs&R)zMDq8F2NcZ`&5z_+h8SA;xb#?jPtG5G!%Ezd&D| z;?+t#B4+u+we@T&E|1;2O&D7~C3al3d|Ptko>)->x5YQFRh0P;-L%n-VT3($-(|YT zcTdQ+6)zvoqFAjyoON&(H*zA&>tMx&oSe8)us}gU7%Wgw8U_pWuR!b6^H)0MuR#A5 z=>NR}{n=FFa=1bXMu@mvu1p}5N!ffJf$@ZL9w8KQxl*oN$W@5=e7021=F6pQok#^Z}HE}P4j;u2iI<4a^Bo=Akt1Y8N2 zNTHWI_rpG(K0Eq z?)sriYR^iLr{z*()|mb1reM|xFbv0Zb`1_@jS$0eA;!VEm>}Y}?(r)%wr0YS?UK%- zp>KQdZ8e(vyvZlVnsdFTWITBt?K=O}jgXc8(Y>JB_^pbfI^BlL#Tzc!u z%UgZVpLsOkgQZhZxmBH#I%N`i|=}VM)}c zxm%lOjykZn@9E1yC6iOlId#!gW%Fe0Q)q)VqZgfAv!v;9-bQ5RN@tgJz}kOnhkWUlZ?0vRY@OQO?v>T$bNy4}E4l@~dJ;O~;=`{7mrC8MnyD=xP4=w0CJgB?FtX-ukXhZdh1rz#l&2Qe!4SIXw>b8c7Dap;3 z4@+dM*32t(d*>Oanr~^;Y-rr;zAZyU7cxCR1r*+0yfVVEVEv0tJWk*>XP+g5x~*F) zT{S!H(befYZbqR|)32K53@CZK2^-<;w>o@l2T#F!_tW(n?^T2qted`(@0n+^cHKjd z71+DC#@=?%ZPvLu4mlU6UGjaH|G_rDi(Jg!_O#0fT^z<6vnmm`y4Qa+y}kq{h$M{qE5KL4JAg83X?I(N3j6l|%0 zFW}+0lr4}+xa3^@gPE zZ8PrdPKF5=p^G$3;q&%IcAbsg4~IJzbc?-6kDGCGJay%kD@PMTThD2zD%jinvT^3_ zX!)&Hl(O;rRxQks@6P97#-G;i6%eiu8(9qNIe54Hh34APjN=(6pN0hY?N_(qgwUKd zv$lpzN(@#_AOC(><0H#vdMx(-$J%^`thluqch(|PDQBr$Wy|ibXI+}YG|#k(s0d3O z7}0HH;o7Tp{89%#STl0ky8HvIqb3s{u5ij|+In2yQAeiuT>B@{rR~5irF95#)5mr0 z&2_IoCzeE z)ggY&qpdm9s~2r6A2WUP#FqQr23;!{FtjvH#rU|;=DsOQy|DF`2Z_W^xu41KjvLGm zOSkcF4>PrY89mG)G9h^Ky>7y>c_p`I7+sxMA~1=&;?lGGhGx6y3A-oP+tPJq4@uW` z#%rWq2cOz-XN^N@Zct+06c)BAeJZ2ojN-aPx0rTh z=55KM=Es(n-`($Ze~+eM$+MQXhig9+4@cKs<&|^N-HbaAe%`q0>p6w1w1Z2+3*%=V zen1{!>*%69~uQ^Hw_*lCQS-Tc2 zTi(n%Vd(y8F`r(RtS;#`>*+m)_2bm`)*pNCZgR1Bp0ios7T$}7g!Ylfw_TkX)cJDw zr??EsiH0wmX zdSdwYt-CYV%ziG)Sbctb;6Af|IOPLF@2zc}vi?Gg1FK3NNbI&Z@6%(g=0O`1pBFY( zl1%@kr~8@O7e&tGw!AAI||>+8Ks+Vb0k4&RgWF+$#WLEO+QTLQ+VWJLFzH=w9= zN7NgPFu(02d~RkDIkZ(#>h?XB?&%SJmpi-0Imu5LM=tC}ya`P&wCg>l z-aZ$fbNl1Oftxo%__Q842z9XxN~PXG7#?}b?^th1=vVgRZyEQ$au6CA!m2d0Z&c?m zJ%bm{Mk~`;#r~Rciu=w9QxD8r_r&;}@$iIk4`$2m?(?>fyjM8={Oxh}Eoh0CD2VM zvv2f!A+;)%?w(upsaMs$ZZm23kB%?87S(#_Ks34RdbmITiRWR{HQtAa zJg@G?gs_dnj-1(+;J2a3s$}ByS3_sb-8*7Urx2K>59i z_^Xj7?Vph0COfe8qwV@Pp6IL*UvbDy+V0g%=+-fA-}Y4>DnH%tP`Py7Mry9{-ZAZl zn)ZKmaMX$2Ic-|LFl{|T_V~1VM?&w|V)cTa6>D3qwizJX<~-$@`a^X8Nah4wqUqo} zzT4Ez4;ma{FE|uoX?m`!=j*EJ4l zD(lY{G_*5GV9jc`R@8ah&pd^{BJ)>dYQ^*oFTVW0E;72r?Z39~U)%Su?fcjE{oii; zl4%_RiAaI*1Z=rfz?bs*I8Q3a*b=UkOJE#aO2`SJluz)u1R<0WJPAiGmy6gETrR=b zJPwB|AIPXl z(Efhv#z5%+GEv(C*VJB^cnFaZpF00CLEF=i9idyu^k;{62@4JL4(sI2=JDAW8}sqT z-SO{abR4H+8T7+g25p@_qr>d=F5{LxsILZZ4Qb_i{F&mb+4n!5PT{Y6BOS*$`qXV* zMhC`WiwwEjy?-mIgoEL_%#jub+89=O{n<|8UBa9~!@Qkz1abljIr(_wzx0cazqOQh zUA9A}dOSI_M{!)!A%m@YjC=m7^5VUl*}HNIUJUTAmr!Db-Zy1!>M86qY<;(BgL3K& z^q$^_*Wmq-_dAMryJ1y5o*sBPZ00SS*ET`NmRr8CeNf=?40ow3QBH2MJ>|;GMz@A3 z3KBc!Xb!Kce%g;UuD8$4RqMqTFFSp_6eHLxyH@IVvBbA(nCqv>_q&-mc3T|zIKVGF ztyNa>E9=~u^}J~J7mBVa&DeX_+V<=+-M_=oMTc{T-8~-^zP7{c{Jr#j$+;Ih-9B0O zMvD=%pZO%5YL^sqrb|G9TmOCL8K3;}3u31omxgvooceCg`~Lmcuan$q)M#58bJqPf z??2G~MAF}p4@kxf9ZVH7y5R1m#48JkTXnTE*w@Ri-_#){FYhQB} zbu?Fhl}rLTS(+~{{7S4KFUp?{QiOHTrG&S}M3^9tm&X~68*ZbH<^0w?VzD-G4<|Yw z<6@@9%mJf2QAU4?rBW~xVJ?rdBgkj)S4FUE5Rf^$;r$ zKVt3NM(xR%^$^Byk?2?xE{@&%eFx^vkk)7FE~Z9oS~6PG{01PtBa~!A_iX zYEG}SJ@MfJO8R<5Tyuv)1vBnU{Nz{L-g{DPiu?AEQ?3jflP?TgFutE(T;GFDN2Q-1 zK4HS*xuN$CW<3%NZSmn*_Xwfd@-nhM)kRaXQoze^p03PI+F5EpWb*l=r=CX9KG7qb zZ40X(v@5%o@%rJb-cw!8-CE={?s9bDl)LA*tQw=;@H}qu?2^h0yGFHNU^0tLwzj~b zBq8}eI4D^|s>@$Z$L9UjbbmFS=U+|te}Sg^yk;m9Vr-s5q>%A>3b{fi;z>C&iBKjJ z2>Al3NWv2eq&&7jAQEsyJb?%oaQPgCOo(&jn3T`vNkpVw{k^%Gw5z{2N9%HcWD2n0 z`D`hVkFgb8fkZ0gVQd+jBaq+5*nOAm4}$ zY1M}0BcA@}e+LLjn5D4^i8GaAY}7KHj$CL`M8CfL%8qecO+T2XIiG#Dd$;B#r=P=4 z?t{{Ub9bK3dGqY}Y18eJKHdC=&v#$&WRlFx?vY8t>roPBxJKWk&MbOB+f$EvZ~se0dGu`*>ZM zQrdiH;KACXMT_+F51sx&eXih;!ntGy5nxv#E{J8vda1FQpGfj z=f?|~+1FzW-p8cnQ8AIC&p!FYt@A^!&@;P_<4BgPw4s0J_S%d8ZY;3T7{xX=l#`_~*q4wweWw3wCV4tTP4la@N`COqw zh+|xwBa{g^LIp=eNVps}hI2R^5r^PNaG^|wvDqR%p%4jVY>7-nDEI;nF4v{0d{1&} z(o~!<9*@W4OJxc+4{poj@MIhb7gNZ25-FD_Aj3G{Pcil9{HqkxkBtBJ3FfQNk8Xl_ z_Vc*UkLQ@Ld{lo0c@F8oH)3Nq;u}4b|nKtR+G1268)Ne*o#<@P6A9JZv(62JiS(G$qVN|JQ z{uhyy@5$2t{zwXZpX$FFNzr}d>c1FCsbyX1=4-5>OL?#MqmHZ^GqX~?p67SkK54Mj zMl)?yPO$2v#y#5#XtODc|T6wNYwXF|Q&;T`>Csd8lu+aun_ zr$Ls9$(#dw8@oR}`Ef|ff`I9ViBH`p4!$s*K9VAiwki%U#^fVBz!)>=5q;-3>QeaLMiz!^0&_Q52v>u zIoFkc*!KC2Wv{QC>zXgUzxj!O{ev&P*O-4_I@j!)_i?6zfinrqpeE@J9Gdv~-Q{&x z)%&WY82+nrgAiLdL2 zANi0~@^Z}!@z^O|gYOm?JH(t?<$k|E)2-un>73yg7v~SZ5uWH|v?^pvuFN48yLPov z{lZI*rJpX{I5vHxV9ldOKEc{Il^wI`WzYNl8l0HWupoz?6Y!GfKI2wE-1X#J9|8h5uIg^GB0Fcp zM%Nu(;(VXIS+PC`+xV$V_X$lq_p}+BG4F(C>N(ra#%2>j&SX0>ciSzz>wNUn$UBxh zM=oU@h-&smV`J0CFKPc6o3YN^ptTmhX3GK=Zr_nxT*w*OJoC5T3aT9k_+FgsEA}E+ zXa+M+Xng>Mw^QP!S! z+3O@`+$C$Ax{Nwl@{V^i=}OtM4m%EYWQ9TeO+& zxufrnP3N6%&W;T8t5*^|_t{JALR-9i;;8wz#$CNSqb<*RY2>rYgpdS(@47wf2Nz|p zF+PxEZRgpb@q)w`g_CA4R9P2#530&)ak#6cQ};_RZG7+C==kcvm>l-BI#pqQ?_15Q z9`CX(@Cws+N$HZUb9!BGFf4Szq~1PR=}YD}xu9Bo-Ta_n*kjt%26vJplb(1@JkYO4 zpG8*`@f&!8JM7Iri&FfR*Kc1&{wuG4<@JA3UO$^cGATzUlS&1AjDr(A0>e2%g-|Z% zh$L)|LL?`+0);}x;SpSp49B@#86jZ{0v`|*3l{!sk(_ungSY@`eN7z*7O!$%myLj74}eH-}3VsGDH zFBG86Ez#t=#V$Q2)hrae1w$t5AKgO1fG^){`f(7)gj^Wt?OS8JT&G|elq*;UWq{6h zsf(6SV-`J)9qM$RKDx_IEAb}-H2`%agK(zBJ= zHtV5}?K@`TuO9_pI^65xx;M^FAJX=7Ru&7AR8Q)=UEAfiV)dk3vXjAkrZ=$QiEZ7nm-VyU z+b`ZUssEO(RIGmgyNiZqmhHawZa;6)(x46fA7wl#ew{IUAN6kcEt4?*QOcml&5Dl2 zJ1?EywAJ$}@~d#bHilq5u#zEI|99yBuO9l(8kNAg3WZD}=SeY)%@c5N4CBir5-vxA zvvCQVEf*3Z0fs5K3aLn@5c1dxj4cshLWzVY=kfV`(z*N|OMlj=5-!H(OC@YV!IueS zY)sC@xB`Ml@Ocuxh$F;6qZ*U~c!{LG(0_b^iGtV&A*Kn`8q{c_-4!ZzvP3Oc#@7_0 zd;%rT5F(FH=s|2#gtBz+c^hgN()HE6pnxWg39G44Hkk^Q`KVCJi^f6-D}>vaz$4Te z2^2r1K#f2O1)XknrlP!~qT8Jj4E{Dv)9E3n_9J0 zZ;KNyN{`*T=E?H~&x-CX84%rd+sH8*#u&?E<~Isk4{Xto?{RBzUD~4i&FUD%pZ2~~ zFZ!ZGYPRFdoRX%8I`)XYeSYS-xScJ=W%C;j*6t5z9MkZ=3+MUU2GSNy4qxlHcScmD z&x!ngqsCmlR5sdeSoeeBi!QZ6RjP+~&9=RZXzII&x2MZZ$6mSZ=Y(c$ESApLUU;>S z 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302204004-Config.rsc b/MikroMaster/20260302/20260302204004-Config.rsc new file mode 100644 index 0000000..2046c04 --- /dev/null +++ b/MikroMaster/20260302/20260302204004-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 20:40:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302210004-Binary.backup b/MikroMaster/20260302/20260302210004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a6a28b6d68fe31bccc8a4b7dffea6e2ccb1d4e3c GIT binary patch literal 289700 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 x7m+ElfK1m= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302212004-Binary.backup b/MikroMaster/20260302/20260302212004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..adc215ecb19ba1ece21e987c0b9d39dd3a21ad87 GIT binary patch literal 289700 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 x7m+ElfK1m= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302212918-Binary.backup b/MikroMaster/20260302/20260302212918-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..919fd95416db605a9dffcb05ae7ea80a0c7bc32b GIT binary patch literal 289700 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

    -~T@E@e#?YPJIa6Ql?3}S9+;mNGRID)$ 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302212918-Config.rsc b/MikroMaster/20260302/20260302212918-Config.rsc new file mode 100644 index 0000000..e04170f --- /dev/null +++ b/MikroMaster/20260302/20260302212918-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 21:29:18 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302214004-Binary.backup b/MikroMaster/20260302/20260302214004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..bcfe0c11ca892fd7a5652d3aa43d27db099b4e93 GIT binary patch literal 289700 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

    n-OOlAThjT8@>2+yPgRB9fF9MX` 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

    hRjcKo6{Gm~#JC8uWJ~Hq$DCgabBCtOwur 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 A?f?J) literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302214004-Config.rsc b/MikroMaster/20260302/20260302214004-Config.rsc new file mode 100644 index 0000000..43f0755 --- /dev/null +++ b/MikroMaster/20260302/20260302214004-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 21:40:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/history/20260220/20260220092832-Diff-Config.rsc b/MikroMaster/history/20260220/20260220092832-Diff-Config.rsc new file mode 100644 index 0000000..e69de29 diff --git a/MikroMaster/history/20260220/20260220110005-Diff-Config.rsc b/MikroMaster/history/20260220/20260220110005-Diff-Config.rsc new file mode 100644 index 0000000..ea88227 --- /dev/null +++ b/MikroMaster/history/20260220/20260220110005-Diff-Config.rsc @@ -0,0 +1,8 @@ +1795,1796c1795,1798 +< ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ +< root.mnuc.backuper\r\ +--- +> ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ +> \r\ +> \n\r\ +> \n#root.mnuc.backuper\r\ diff --git a/MikroMaster/history/20260220/20260220110205-Diff-Config.rsc b/MikroMaster/history/20260220/20260220110205-Diff-Config.rsc new file mode 100644 index 0000000..cd4e821 --- /dev/null +++ b/MikroMaster/history/20260220/20260220110205-Diff-Config.rsc @@ -0,0 +1,7 @@ +1795,1797c1795,1796 +< ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ +< \r\ +< \n#root.mnuc.backuper\r\ +--- +> ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ +> root.mnuc.backuper\r\ diff --git a/MikroMaster/history/20260220/20260220110853-Diff-Config.rsc b/MikroMaster/history/20260220/20260220110853-Diff-Config.rsc new file mode 100644 index 0000000..6d0f9a2 --- /dev/null +++ b/MikroMaster/history/20260220/20260220110853-Diff-Config.rsc @@ -0,0 +1,2 @@ +1797d1796 +< \n\r\ diff --git a/MikroMaster/history/20260220/20260220111036-Diff-Config.rsc b/MikroMaster/history/20260220/20260220111036-Diff-Config.rsc new file mode 100644 index 0000000..263d364 --- /dev/null +++ b/MikroMaster/history/20260220/20260220111036-Diff-Config.rsc @@ -0,0 +1,2 @@ +1796a1797 +> \n\r\ diff --git a/MikroMaster/history/20260220/20260220142012-Diff-Config.rsc b/MikroMaster/history/20260220/20260220142012-Diff-Config.rsc new file mode 100644 index 0000000..be5bc7f --- /dev/null +++ b/MikroMaster/history/20260220/20260220142012-Diff-Config.rsc @@ -0,0 +1,8 @@ +35c35 +< # channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +51c51 +< # channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding diff --git a/MikroMaster/history/20260220/20260220190012-Diff-Config.rsc b/MikroMaster/history/20260220/20260220190012-Diff-Config.rsc new file mode 100644 index 0000000..b9340d2 --- /dev/null +++ b/MikroMaster/history/20260220/20260220190012-Diff-Config.rsc @@ -0,0 +1,7 @@ +1016,1018c1016,1017 +< disabled=yes dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina \ +< log-prefix=VPN-all new-routing-mark=To-VPN src-address=10.30.30.0/24 \ +< src-address-list=!NoWG +--- +> dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ +> new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG diff --git a/MikroMaster/history/20260220/20260220210012-Diff-Config.rsc b/MikroMaster/history/20260220/20260220210012-Diff-Config.rsc new file mode 100644 index 0000000..e33c20c --- /dev/null +++ b/MikroMaster/history/20260220/20260220210012-Diff-Config.rsc @@ -0,0 +1,7 @@ +1016,1017c1016,1018 +< dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ +< new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +--- +> disabled=yes dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina \ +> log-prefix=VPN-all new-routing-mark=To-VPN src-address=10.30.30.0/24 \ +> src-address-list=!NoWG diff --git a/MikroMaster/history/20260221/20260221130011-Diff-Config.rsc b/MikroMaster/history/20260221/20260221130011-Diff-Config.rsc new file mode 100644 index 0000000..4b890b5 --- /dev/null +++ b/MikroMaster/history/20260221/20260221130011-Diff-Config.rsc @@ -0,0 +1,8 @@ +35c35 +< # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +--- +> # channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +51c51 +< # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +--- +> # channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding diff --git a/MikroMaster/history/20260224/20260224050012-Diff-Config.rsc b/MikroMaster/history/20260224/20260224050012-Diff-Config.rsc new file mode 100644 index 0000000..d533e73 --- /dev/null +++ b/MikroMaster/history/20260224/20260224050012-Diff-Config.rsc @@ -0,0 +1,2 @@ +293d292 +< add address=10.30.30.33 name=oxidized.vados.ru type=A diff --git a/MikroMaster/history/20260225/20260225004202-Diff-Config.rsc b/MikroMaster/history/20260225/20260225004202-Diff-Config.rsc new file mode 100644 index 0000000..2c26ee4 --- /dev/null +++ b/MikroMaster/history/20260225/20260225004202-Diff-Config.rsc @@ -0,0 +1,8 @@ +35c35 +< # channel: 5240/20-eeeC/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +51c51 +< # channel: 5240/20-eeeC/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding diff --git a/MikroMaster/history/20260225/20260225012726-Diff-Config.rsc b/MikroMaster/history/20260225/20260225012726-Diff-Config.rsc new file mode 100644 index 0000000..976bb11 --- /dev/null +++ b/MikroMaster/history/20260225/20260225012726-Diff-Config.rsc @@ -0,0 +1,8 @@ +35c35 +< # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +--- +> # channel: 5240/20-eeeC/ac/P(20dBm), SSID: vados5g, local forwarding +51c51 +< # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +--- +> # channel: 5240/20-eeeC/ac/P(20dBm), SSID: vados5g, local forwarding diff --git a/MikroMaster/history/20260225/20260225120026-Diff-Config.rsc b/MikroMaster/history/20260225/20260225120026-Diff-Config.rsc new file mode 100644 index 0000000..5ac2e92 --- /dev/null +++ b/MikroMaster/history/20260225/20260225120026-Diff-Config.rsc @@ -0,0 +1,7 @@ +1017,1019c1017,1018 +< disabled=yes dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina \ +< log-prefix=VPN-all new-routing-mark=To-VPN src-address=10.30.30.0/24 \ +< src-address-list=!NoWG +--- +> dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ +> new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG diff --git a/MikroMaster/history/20260225/20260225150026-Diff-Config.rsc b/MikroMaster/history/20260225/20260225150026-Diff-Config.rsc new file mode 100644 index 0000000..14f2f81 --- /dev/null +++ b/MikroMaster/history/20260225/20260225150026-Diff-Config.rsc @@ -0,0 +1,3 @@ +930,931d929 +< add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ +< disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist diff --git a/MikroMaster/history/20260226/20260226084004-Diff-Config.rsc b/MikroMaster/history/20260226/20260226084004-Diff-Config.rsc new file mode 100644 index 0000000..b51abb7 --- /dev/null +++ b/MikroMaster/history/20260226/20260226084004-Diff-Config.rsc @@ -0,0 +1,8 @@ +35c35 +< # channel: 5220/20-eeCe/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +51c51 +< # channel: 5220/20-eeCe/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding diff --git a/MikroMaster/history/20260226/20260226092005-Diff-Config.rsc b/MikroMaster/history/20260226/20260226092005-Diff-Config.rsc new file mode 100644 index 0000000..ae6fb89 --- /dev/null +++ b/MikroMaster/history/20260226/20260226092005-Diff-Config.rsc @@ -0,0 +1,8 @@ +35c35 +< # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +--- +> # channel: 5220/20-eeCe/ac/P(20dBm), SSID: vados5g, local forwarding +51c51 +< # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +--- +> # channel: 5220/20-eeCe/ac/P(20dBm), SSID: vados5g, local forwarding diff --git a/MikroMaster/history/20260226/20260226220005-Diff-Config.rsc b/MikroMaster/history/20260226/20260226220005-Diff-Config.rsc new file mode 100644 index 0000000..099c5f9 --- /dev/null +++ b/MikroMaster/history/20260226/20260226220005-Diff-Config.rsc @@ -0,0 +1,7 @@ +1019,1020c1019,1021 +< dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ +< new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +--- +> disabled=yes dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina \ +> log-prefix=VPN-all new-routing-mark=To-VPN src-address=10.30.30.0/24 \ +> src-address-list=!NoWG diff --git a/MikroMaster/history/20260227/20260227150358-Diff-Config.rsc b/MikroMaster/history/20260227/20260227150358-Diff-Config.rsc new file mode 100644 index 0000000..e69de29 diff --git a/MikroMaster/history/20260227/20260227154850-Diff-Config.rsc b/MikroMaster/history/20260227/20260227154850-Diff-Config.rsc new file mode 100644 index 0000000..e69de29 diff --git a/MikroMaster/history/20260228/20260228043319-Diff-Config.rsc b/MikroMaster/history/20260228/20260228043319-Diff-Config.rsc new file mode 100644 index 0000000..774541f --- /dev/null +++ b/MikroMaster/history/20260228/20260228043319-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 04:33:19 by RouterOS 7.21.2 +--- +> # 2026-02-27 15:48:50 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228044004-Diff-Config.rsc b/MikroMaster/history/20260228/20260228044004-Diff-Config.rsc new file mode 100644 index 0000000..731074f --- /dev/null +++ b/MikroMaster/history/20260228/20260228044004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 04:40:04 by RouterOS 7.21.2 +--- +> # 2026-02-28 04:33:19 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228044733-Diff-Config.rsc b/MikroMaster/history/20260228/20260228044733-Diff-Config.rsc new file mode 100644 index 0000000..86b8d65 --- /dev/null +++ b/MikroMaster/history/20260228/20260228044733-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 04:47:33 by RouterOS 7.21.2 +--- +> # 2026-02-28 04:40:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228050004-Diff-Config.rsc b/MikroMaster/history/20260228/20260228050004-Diff-Config.rsc new file mode 100644 index 0000000..6450c20 --- /dev/null +++ b/MikroMaster/history/20260228/20260228050004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:00:05 by RouterOS 7.21.2 +--- +> # 2026-02-28 04:47:33 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228050259-Diff-Config.rsc b/MikroMaster/history/20260228/20260228050259-Diff-Config.rsc new file mode 100644 index 0000000..2d7339f --- /dev/null +++ b/MikroMaster/history/20260228/20260228050259-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:03:00 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:00:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228051202-Diff-Config.rsc b/MikroMaster/history/20260228/20260228051202-Diff-Config.rsc new file mode 100644 index 0000000..2660647 --- /dev/null +++ b/MikroMaster/history/20260228/20260228051202-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:12:02 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:03:00 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228051337-Diff-Config.rsc b/MikroMaster/history/20260228/20260228051337-Diff-Config.rsc new file mode 100644 index 0000000..c435616 --- /dev/null +++ b/MikroMaster/history/20260228/20260228051337-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:13:37 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:12:02 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228051612-Diff-Config.rsc b/MikroMaster/history/20260228/20260228051612-Diff-Config.rsc new file mode 100644 index 0000000..3fd61aa --- /dev/null +++ b/MikroMaster/history/20260228/20260228051612-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:16:12 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:13:37 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228051903-Diff-Config.rsc b/MikroMaster/history/20260228/20260228051903-Diff-Config.rsc new file mode 100644 index 0000000..aa12461 --- /dev/null +++ b/MikroMaster/history/20260228/20260228051903-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:19:03 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:16:12 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228052004-Diff-Config.rsc b/MikroMaster/history/20260228/20260228052004-Diff-Config.rsc new file mode 100644 index 0000000..8017dea --- /dev/null +++ b/MikroMaster/history/20260228/20260228052004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:20:05 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:19:03 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228055323-Diff-Config.rsc b/MikroMaster/history/20260228/20260228055323-Diff-Config.rsc new file mode 100644 index 0000000..0e8687d --- /dev/null +++ b/MikroMaster/history/20260228/20260228055323-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 05:53:24 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:20:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228060004-Diff-Config.rsc b/MikroMaster/history/20260228/20260228060004-Diff-Config.rsc new file mode 100644 index 0000000..7612d7d --- /dev/null +++ b/MikroMaster/history/20260228/20260228060004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 06:00:04 by RouterOS 7.21.2 +--- +> # 2026-02-28 05:53:24 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260228/20260228062004-Diff-Config.rsc b/MikroMaster/history/20260228/20260228062004-Diff-Config.rsc new file mode 100644 index 0000000..a04a74c --- /dev/null +++ b/MikroMaster/history/20260228/20260228062004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-02-28 06:20:04 by RouterOS 7.21.2 +--- +> # 2026-02-28 06:00:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302143118-Diff-Config.rsc b/MikroMaster/history/20260302/20260302143118-Diff-Config.rsc new file mode 100644 index 0000000..9e3bae7 --- /dev/null +++ b/MikroMaster/history/20260302/20260302143118-Diff-Config.rsc @@ -0,0 +1,12 @@ +1c1 +< # 2026-03-02 14:31:18 by RouterOS 7.21.2 +--- +> # 2026-02-28 06:20:04 by RouterOS 7.21.2 +35c35 +< # channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding +51c51 +< # channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +--- +> # channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding diff --git a/MikroMaster/history/20260302/20260302144005-Diff-Config.rsc b/MikroMaster/history/20260302/20260302144005-Diff-Config.rsc new file mode 100644 index 0000000..2ea4b98 --- /dev/null +++ b/MikroMaster/history/20260302/20260302144005-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 14:40:05 by RouterOS 7.21.2 +--- +> # 2026-03-02 14:31:18 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302150004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302150004-Diff-Config.rsc new file mode 100644 index 0000000..ac6fa4f --- /dev/null +++ b/MikroMaster/history/20260302/20260302150004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 15:00:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 14:40:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302152005-Diff-Config.rsc b/MikroMaster/history/20260302/20260302152005-Diff-Config.rsc new file mode 100644 index 0000000..a73c912 --- /dev/null +++ b/MikroMaster/history/20260302/20260302152005-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 15:20:05 by RouterOS 7.21.2 +--- +> # 2026-03-02 15:00:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302154004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302154004-Diff-Config.rsc new file mode 100644 index 0000000..8cc371c --- /dev/null +++ b/MikroMaster/history/20260302/20260302154004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 15:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 15:20:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302160004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302160004-Diff-Config.rsc new file mode 100644 index 0000000..06f2708 --- /dev/null +++ b/MikroMaster/history/20260302/20260302160004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 16:00:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 15:40:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302162004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302162004-Diff-Config.rsc new file mode 100644 index 0000000..ced859f --- /dev/null +++ b/MikroMaster/history/20260302/20260302162004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 16:20:05 by RouterOS 7.21.2 +--- +> # 2026-03-02 16:00:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302164004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302164004-Diff-Config.rsc new file mode 100644 index 0000000..8df948c --- /dev/null +++ b/MikroMaster/history/20260302/20260302164004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 16:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 16:20:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302170004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302170004-Diff-Config.rsc new file mode 100644 index 0000000..0652aff --- /dev/null +++ b/MikroMaster/history/20260302/20260302170004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 17:00:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 16:40:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302172004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302172004-Diff-Config.rsc new file mode 100644 index 0000000..6e131ef --- /dev/null +++ b/MikroMaster/history/20260302/20260302172004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 17:20:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 17:00:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302174004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302174004-Diff-Config.rsc new file mode 100644 index 0000000..f67b261 --- /dev/null +++ b/MikroMaster/history/20260302/20260302174004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 17:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 17:20:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302180004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302180004-Diff-Config.rsc new file mode 100644 index 0000000..ed22818 --- /dev/null +++ b/MikroMaster/history/20260302/20260302180004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 18:00:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 17:40:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302182004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302182004-Diff-Config.rsc new file mode 100644 index 0000000..dd3443b --- /dev/null +++ b/MikroMaster/history/20260302/20260302182004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 18:20:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 18:00:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302184004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302184004-Diff-Config.rsc new file mode 100644 index 0000000..79b8a10 --- /dev/null +++ b/MikroMaster/history/20260302/20260302184004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 18:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 18:20:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302190003-Diff-Config.rsc b/MikroMaster/history/20260302/20260302190003-Diff-Config.rsc new file mode 100644 index 0000000..96b49c0 --- /dev/null +++ b/MikroMaster/history/20260302/20260302190003-Diff-Config.rsc @@ -0,0 +1,52 @@ +1c1 +< # 2026-03-02 19:00:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 18:40:04 by RouterOS 7.21.2 +2663d2662 +< \n :global InitSetup;\r\ +2665d2663 +< \n :global ScriptUpdatesCRLF;\r\ +2670a2669 +> \n :global ScriptUpdatesCRLF;\r\ +2683c2682 +< \n\r\ +--- +> \n \r\ +2688d2686 +< \n\r\ +2697c2695 +< \n \r\ +--- +> \n \r\ +2802,2812c2800,2803 +< \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ +< lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ +< \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ +< \$ScriptVal->\"source\")) do={\r\ +< \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ +< . \"' source did not change. End of lines set to CRLF.\");\r\ +< \n if (\$ScriptUpdatesCRLF = false) do={\r\ +< \n :put [ :tolf \$SourceNew ];\r\ +< \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ +< ) . \"' source update end of lines to LF.\");\r\ +< \n }\r\ +--- +> \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ +> iptVal->\"source\") do={\r\ +> \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ +> \"' sources did not change.\");\r\ +2814d2804 +< \n }\r\ +2816c2806 +< \n\r\ +--- +> \n \r\ +2904,2905c2894 +< \n :global InitSetup (a);\r\ +< \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ +--- +> \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ +3755d3743 +< \n:put \"Add or/and fix Global scheduler...\";\r\ +3773d3760 +< \n:put \"Add or/and fix Update Script scheduler\";\r\ diff --git a/MikroMaster/history/20260302/20260302192004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302192004-Diff-Config.rsc new file mode 100644 index 0000000..fec5867 --- /dev/null +++ b/MikroMaster/history/20260302/20260302192004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 19:20:05 by RouterOS 7.21.2 +--- +> # 2026-03-02 19:00:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302194004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302194004-Diff-Config.rsc new file mode 100644 index 0000000..94cdeab --- /dev/null +++ b/MikroMaster/history/20260302/20260302194004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 19:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 19:20:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302200004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302200004-Diff-Config.rsc new file mode 100644 index 0000000..01ef264 --- /dev/null +++ b/MikroMaster/history/20260302/20260302200004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 20:00:05 by RouterOS 7.21.2 +--- +> # 2026-03-02 19:40:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302202004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302202004-Diff-Config.rsc new file mode 100644 index 0000000..e5f6b59 --- /dev/null +++ b/MikroMaster/history/20260302/20260302202004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 20:20:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 20:00:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302204004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302204004-Diff-Config.rsc new file mode 100644 index 0000000..6e86834 --- /dev/null +++ b/MikroMaster/history/20260302/20260302204004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 20:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 20:20:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302210004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302210004-Diff-Config.rsc new file mode 100644 index 0000000..db4c235 --- /dev/null +++ b/MikroMaster/history/20260302/20260302210004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 21:00:05 by RouterOS 7.21.2 +--- +> # 2026-03-02 20:40:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302212004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302212004-Diff-Config.rsc new file mode 100644 index 0000000..68fa78b --- /dev/null +++ b/MikroMaster/history/20260302/20260302212004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 21:20:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 21:00:05 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302212918-Diff-Config.rsc b/MikroMaster/history/20260302/20260302212918-Diff-Config.rsc new file mode 100644 index 0000000..2131c20 --- /dev/null +++ b/MikroMaster/history/20260302/20260302212918-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 21:29:18 by RouterOS 7.21.2 +--- +> # 2026-03-02 21:20:04 by RouterOS 7.21.2 diff --git a/MikroMaster/history/20260302/20260302214004-Diff-Config.rsc b/MikroMaster/history/20260302/20260302214004-Diff-Config.rsc new file mode 100644 index 0000000..8eb0470 --- /dev/null +++ b/MikroMaster/history/20260302/20260302214004-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 21:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 21:29:18 by RouterOS 7.21.2 diff --git a/MikroNUC/20260220/20260220072118-Binary.backup b/MikroNUC/20260220/20260220072118-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..4e6c3f514ece0aee8d49a5e5f3f4b764f541c9a0 GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220072834-Binary.backup b/MikroNUC/20260220/20260220072834-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..31f2e6b9f2001a7fe2772d2a19963d2caac94254 GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220072919-Binary.backup b/MikroNUC/20260220/20260220072919-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..452bc74e54db7eec90d77af48bf0733af7630d0c GIT binary patch literal 300264 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

    tq4d;UJ0cV=_)8Oc_p0ua5fuc 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220083844-Binary.backup b/MikroNUC/20260220/20260220083844-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..c11ba0ce6bf0c5c8e4a550a02aba05804cfdd211 GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220083924-Binary.backup b/MikroNUC/20260220/20260220083924-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..f17f77667d22376820122eb9a48427d17ccc1c80 GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220085626-Binary.backup b/MikroNUC/20260220/20260220085626-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..6b52a90a57e0d26f28b158f6f607ce2568dcb839 GIT binary patch literal 300264 zcmeFa2Ut_f(?32Z36Rj6fTBnd!4f#>iHcGLL_s==1x$rV35I}R1F>O4?7d>|*ir0a zSFm^NiuGEsp~C;!lLVvU)%*VM_xs-Wcg@4IXL8swJG(PG`{B)}i%uXnTSVVPXI@jP@O2005~{m1m|>W~ZsiOLMKQtE;on z(A@#R3qqJ=fRz{+LI{%rKm`C227nnrEoKO{fI%${^q`hnS65d@gIXsrhgv5}icp?v zL9|>;MV0EIY*y;tC>0qhd1``ZhA1J;Q!Gm`)^w|#reSn#2O&%osKu;MIn)N$3~F21 z>fA)l7)YctVMek_mp0P$P9n{ei>2xFG?k}lDklNJXAOf?1iQ1|gm_lVwV`)G;ghdl*obz$jhB~h!Y(rnAT#_KA2m5rV0_IM_LYPgVb`hW{gGm9fL;y?<0Q~_CA7BaqNCN-^ zs3rP@`Zfpvh62Da0LVppgVZM%P}hm^(F35FQ2}Vy5&#-00f44&j08WsHzJDh=zK-b3|3q{KB0_YG|B>7<9l2ruaJgX(%B@xr(^heb>-IL=W=8HOXX&H&E@#;L_%(AQde%SKbIRa z&41m#{omKqJn!B8NuLS1sY%^+u_cn*&(=jIu`UW^92OUsvgjfSTS{lk*un#(L-9_>Lrg3kQWV1Q@5Fs};sVldLpUaK=FO}Qs zZPn+U*o55Fq^{h0{9JClf2rJhb&MQ3dkY~qHK{ANc|VsM|6eLM2hZ*w##Rw>QVcB76q^Az=_5^ZFF0wGLutM@Gg(9j%0n5d+7 z&xLXzY=TB6{*BNENuoH-Q=BZ9rmEr*+-LLv{ z5C8%-e4zedP)kMSPy=2h04Ga4OD1dK?iU>7-#se6b97MWR`vLYiMma>Bwmssm-u{B z4QjH!8VfuNXVg~{;^X(F7OJ+E_TN;1_(T;LBR-5;xOWMSjOy+a;;&OQQIW1n6{bkh z*d!kmNWT8UY~;4UPKB)zB3H!2Z%UhIXv#fk1oN)LI%UNi9UIAmj%F zaH1%sLJ6m#G9*;yxu%S{ZW+CSO1VnPXs8ew6{@Wx8lvg6BFjil=Bf)29M^M3K?Sah ziJdytd7e%geUVU{l#zxItYoo7rN|H`qIrov0Xo+J2w|oIU;_Xk9e|j7Xs4fqz$>(O zmI6?z1^_bj1#Q~V=AVY8p`<^O0E5Y5qneYYl6aL;o{%6_rlapjb+phOx*}u_;TIT! ztdbQ8bfK7-p&c~bOwnACrW9&uG-_HJjhZ$O8nuO*JatcJN1$6b3#=)5f)Lm z4647uGNd1uL3-R^8S;CiB-C91 z;yQ^G!t4WpNz_OxGNTv*-_fkH0>G>RkeNX?1+xRdnyBqAoC3fc0I=o&n6t)rXa#_^ z2EgdZDq`x96%f$_fc5}@EU6a&))4?Y0f09E<^zBsdmjjZbp?QK0DvRg%>bY|Z~&-e z01{VY33&iC13r=gVX1ooQ1J|a-kNJ7`i~spvlxK|({hv07YYDEZY3!i`-l)+gk&oK zsP|k6q?qQ7;9LiURIrnwpdP{T>4#vyLJh$gGX^a>+h7x-KnqgA_s+}D`GnCsK;55ozjxtsd z<$>gg#B>~h*5L%YV-9c5SXb_saeKj;vbuEq5v7hEX z^0NA9=$g8^I+2F{SXWmk(a+0%~H8gSyv~`x607PLS%yDF7lJ=1RMw0<1 zkpT+HYUOW125d4JuxVs~$r#Y|reHvQtOxK00~)-=fW~}>sP`C9D+~y?m4)64EBkWg7}pCi?pK3zz)Q6E5YyGhxjK%9YY&X?nU=xc&b2nM?WS377oe5w2BwcB(j0sYq31 z)XTTe-!5Ohf1Z5*OOw|uQK3ptQ`8#<(cd9kOlKvdqP6v(Ctkh(&h)iR6Az$gq$Mka z60LQR{2dY|=}H)REdN>wTO$ce6a!OrWi0+XWUT9t5r=I4c``Qm@62K=MQU<3JyEEX z3=}G*bi(gW{@X>29PEFdi1q(FB5sP9_CgZ=>JmZ&|C;jE-83^=N3MH8mPa-O$MXTa8!a~3(U6SXRrDo~%fa*8^?{jY1!ErE35;bk32$+v}MiLMZ6aEW#A^GF1$m2$QAD zQ{vO5Ds(`W2pXVIFCtZ6dqD^jVHW6&DgyISlnX`ah}nUFA@w<2pdpFT$OzUaaGxv< zt_L&%zC+A7A=tu+Dw8WykSRuZMn<|+sfAJtG_4}xXlayZvgSU*Jhb75P9&5kglP`2 zQXST73P5z42+R=UW2A}Xps^se0-)}5qe1KXfk8l{I&kL%z;GH^JT;(I>8F#Gx$ZX3 zt#cCk6rA~N<8j!&u;O~}N38N)m?HqgJfca^9~)j-EngKn{U~qzP$x9M^@NfXdFo&1 z=2#@9o*NVq(dC9D95$-Zypg1AAD(_x+DLfZ=E#a(MP}z%S-T^~9_8LZ7#PFcY<}?N zH?6TOE7o#z;hp zR}>!9(<1f6q$H+10fQoZ+T5iaOMfT1b$e1-fI35)+gl93D*_C$v5| zA$d3~xhh1%>U=$3t^P;3--a(FY-@+9?xCWfi+R7|gdVtVz( z^q6W%e%CksuZtmdQ+G@MMO-hkP-H})A^3Ioiclz2j-SZZ`|VgZbvV^xUJrs?&EmYlF#@{*_(0N+0gOVjq~Z=MOzEvw(lU}jpH6H88YhTp6l-qa+WL$*&O#Y z?|Ipqyx9jx52Cjh;N0WbfM@RePNX_5o95Q`Wo`Sh0On}gpoyA~B88*2Cn9?I@1g&H zeds446`ug$%aGWa^3fU|ngUJvwnG(KKz{7DFTP6~SWqb}( zhBJjcoG%n|Bpfc6I}U)+;FKPZn#clhaul+0CRZe6N@ZLzPt3$6Y@E%La->|2kSk#E z@d3z_(-=GjI#-75MKU^R6&)E#QyWQ&#z>k%s8?rsg4|E4R5=Evimf0t+H2szfgTch zf?OuZGDNag@jBq&SfwdYRimFGmD|~^}oSF9_FmuaZC@$d6*gCd6*$7 z55wS2``Z@E%9Tsc74=vhwq%mgz`|oomOZyTJ)<{9b3BPnUC|xi9{JAikQ{o)A z+P+`2=eheORnDNS*|DP%Q~S6uyY211uc}wd-L$;}&G&x7-j2Gmva@+l=Bf<43ul(> z3B2Rhzj_YqeGs+Z`1A2w+Kt@1cy-s{p&iRZ*fp_dr>*u?LGDY^t}-Y$-fgmZ6>Qku zVCA!}UU6GIa3i6|I*Y`(@SC+~^q;Lg&YwMX!sN6&Ys{MNnYyY@eBqu!zjH-<=l7<) zyijmAvbsQA(`m)EEwY;;*~K%dJ`-Qjw>}=&b>aM;ciP16^LBYgchB?hm>o5x<*Zw| zT~_k`cyTeipH1c3D$`S`YdhQWJ%g^^_V3ubgd17jE=>QON7bPoLCHcVy9<zD3dP>yK^*4%xb;1yv7!O5bg?*MDzV z$*R{+W?`1=j^-bp#g3n7*x~S_3)82kRHC&L8HoC|bAKc{&rPhIzZF_-p1-jvzZLqo zLjQ9W`in=zX0iD~TqhT&n(}e#oV&Gh?Ldx>RK3Qu&z@E)`V> zuU>Rn>8C{_1D@7N3Z6$fisz9x zYCJ9DH@o%Q#E_~7?Feh@a`J^tccnA>FL+vkOkxwvz*(9-u-enYSxkX;6CC?X&K?VA zs6D#YTG?o=Zy?h#Dmc?W(B-?tif4rpF=Z)kg9lm0 zjC)!A;o`&FlXg#E^QxauqqJ+5P~&E}wFkfV&`se}2TV8Z?=!78$G&E8&91UNE%4fy zKMuVfI`gje8|#o0E6iWnJYM7cg5hi-loz(#nRR7m^SeW3Yce`dPd~c0?vK8P<6`}8 zuiezn>~)ttCBjK~R;FIIb4c~~BvhYiCm z>v!~2Tpz>gNEqmB>Q$q1_sNdj#_A~&o~flVjM5)Z#9L^;yb=+DU{3^&l%OBim9VK`M^9}%Q46si6m`5VO~T+qUo zX(!xg%4ZHyeco5oa&Y9Db*H4Cch1wFH||m|zcJ53f@9*>?JwJ^=jai8rmpLoMXfJy zoWAauN7we3R=ic@xB7&4YB6%x!R>>m8noRoCMlEk45A}8#V)v4Qt|rcL$lf&?+=xj zD~Ho4@#QlYcrY^x%IEYv+k-KThYjB(OKH`lSVl`ZlUi6^QsaqPm-UH}U{{8YS;>!F zIKFQ{N}t1SBZr?KHeo{1+=z#V^PlpDwEp-ax))z*ei^LFgVV3A=5bcG8ZMugSz2i~ zxbXb(@;?&DpDDeZY>Mk1ce;5!@6D6y*eNb1Em}`^4L-hj@`Ll+*N#zbewk7<``U*K zyGMF2G?;~4P-IZ+UC{m_0&Pd|&2LM`Ul7mIm(E>9#7a`-$Ehsom!cq{>jCt&c{T$W7CXRsu=h|A;%1%z+j&{|FS z<_)dUYTsNem8oGE6q#9|rF;lMj;_y6MLv77dxNnh1cNrS z$f=;~a7C}@iXO=P1{XbsaM3b6kF-whtz+Sm74PFE+3; z{31L?6Wk8nG_>VJYzO0F5zq3DPSM)A7sOKZ+5mw8~9R0BNBVRrk6|~Up@!OI1-4|`SmNx4M6D!v1 zXwdz6bxo*eEbjbpP2-rPJGlm*UfX2k3c?59|G?R%>b`1Xp4Gi=omP=Y)GXOEu2KJ- zN~43@8e8ife|&HyWm@}yAxx9kAag!CQJ%t`U}3lY+@_}ew(x666HcGI5nxbh*zrl< zAxDRN+}I{^=@gMX+*ME5r1S6zZCCltaJjj*-S9c4t;(9Ndeqlp+kyqSq2Tn({M?V- z`krJy9VPN}Ws_puu*qB6r?u{sT3j_R9~-*x{D*6iDgEZ}ZTqn2njP^0pH3gLCwHJd z31ak-2W-9-sCM>IDDS(_9g17(#`eC1^4iTAWniA*zU_~v_3qLi!fI?^V6Q?@1Xu zJ})c2wEpd-N~;r*=EKGXoS9j(-J^}gn!=54xgV+)_IkuyxaQu?>h_FS+=7s-QD@Kek0!gx%Zew z&-hiBC9m5Kv;IVSyzo?=L89$7=R!Vx(8M!QFXeaRS;q%?4K}=cJSSdo|4zovvP?VH z>9#LCgV(()et0@`<)OJGSS!(>Fw<(YA^>6G}uHCG*e|sf4TgTh0GYWAt0if2;Zbnwo#{)7Tsa8yB&d zY@Spk5R3U@j)*P8B|H&_g$o!m9s;;YeJ{6rn|Kb{?ph&dFchI1vSziU9!-DN0)GInwK1ixkI7Ugu ziKz;7kV%^E80q2T;e?{m$i2x(as1-t$Q7wyysxInOVebDQf8#9q!P#OQq@3(GU=D1 z(_?Mxx*)e~EaO_5u3JV!ZdnJ1AG&4VMyH#rd7x`}plf)b`}ut1hV4ae*e*PeRHSyp z$du0ebk{f(kshYwhlK?*oN-6BO>6u^Nip1TSCq%d%HhxDrLBx?)%b@}BU~^(17|WB zOq|E!^|Cc#3Xlt?`TD=k-_NY_-H$_ylsgZ+IA%TOO%m4qcB;3*&J?%4Iq!PYH}^Uc z9=~QObGdNLwp6pxXK~WZ_m|{77TXE>_LpQI#$wlYV07gVIZHX)&ArMozP-VclOgHX zUat>55_6%~iWy^TUav_!?=m{pt(@jox;9lgqA9Mtd27j|v$s_ljd!)Lk!ru?MN6&e)HvWmt!eaWFohK*z4h(iZ zR>)UedvWq(fy2z$ju-lMf1v07EGXNm+s-c6JU=MU369q`zsy#?+2UQ!zz#mGw4mGe zZN4MyOkCp?@=61i`|+^pA67)2h#DQ{zv@HKpEzG%oGohRsS^fuE#8)$dbX>u^v+0L zK*qc8e6t2Z)yr3|b3ToEEibAQRdks@K2EtYtMlFKO*ha!yL749-TF{TG-a!K(L}dO zqdalN^Gai0woh;8O&jO<^jV&E>wLw)6E5fAR&tEzZMlibmDPKlhKF6zU$(MtIk0CqEv;MAXV~5nM3r_qm+3Zt4qbowv8RHwYpyMvW8_BSv?}(V{_sQ9yy*PK z0T;Kk-wZn~m~(~yGW=a=TjYEpYoWynkpbh@Gud17hatADuBop4WZ1A9`Ne!`3^Ai*(IX;#bO15ABJ~R-_KhQU zM-R`_tHkrjhc(e_>~jkKspxq4O8ZiYDThqgUHpvo03V*Oyy3{)NsRN^7lNjIkd4_FnUX^Y_9JTO3*-72P6Nu zwz^i;U4A5KLcgh%hmIKEyvB;2X8nt!r)-nrn-&wAHY-cMia(w+`` zIngRw(B+_>O>(AiAB0aaecf_s(-7OzV^95BR_yhO_g>YxbM@?pJ;p2uYu+PjWyjAd zv1f6Zl=h&fuZLfg;4Lp)17m9_4pYy!4Cop*d{gC~tnHr?8r?qDW2A$b_~Ikc&WrKU z9*_GRcBfKY1v^aJta=qZv#CKRlZZFZ{_xB*`{Jv9aZMw$_x4)drfYdr?(NHS_sxH` zi7Y$uooo6XuBhXy8l%&#BnK~gjz7zH1(KG%V>>5c5EzQ#1J<9I1=>Dna(-+nLwa%NLcov+!;xE+OKU1+XQ#on; z1n!2tCVHm_Onk6h(L8zi08!cHiV;fVmkAbQjptbfE7>ARIdSK-Llf)htexv74c?lTzrJJRa&Py`pNO0%{O~iwqWzF*$e$VrpT{>LQ!LNU_6?T4~h0DZ3mRQJP2>A?= zNX%v9QWghiF(v3!!>{@GXh+xZP5}Yzx;qPmu05F6V*HAs6? zKGMT`#Js9bJ}K?jom*-h%gvfk_Iqw_m8`5>pTA;p(pJCI3D;ff$W4pxbo`Y#|7acm ze)F|1OFt|wyS$$3bJ9XA7qu$wc35|`$ccbUNeoz5`YO4TW!E!w!9hdX%=GGf?u2}| zT@UgnhK*Vw{;+^qDVu8c@?(v9RbHAy*(NVq`O`+#KPjs;=YS6&EO^6bdF#bTVv6mX?7 z0Z+^niUm>`m&amAaAE~&NON>nAP$Ga;flmECI?l^VR6JPAsd%TI6@Jd!(;yVnU_G; zUwY={#;=~Nvx88tNR?12lS`8&Uj=y8hwR!SK=DfkVw!zH6#u?ccE*4GlpVdEt-o~4 z?ly|=-oW!nnq{ehV|J6i#u0zTug#!>ZKcBOL*B+_B{=V%ekEr87$gxs=1MP zSG)NiKV`!#p{l%Pp11h*CT0J|CbN&9H_bT7`#65={@9nIocPW0QvCgj?ID@H95UnB z`>JNd%pSM-Mb6SwyRS1DLnfEsinn;5v^uEInc36MEV(Q0P0QRGBf8y9)ojN3mglLI z*os-ErVlDV9emon@Z}d&?K_z4$H(u67&Du%xPs>#8k$%nTDkc28iU?$x~Q5F@ys{| z7O^$1p=8Ch+3n{v&l@E;pQ$%3?za2X6j5K=fki9NZ_MDoWcQzcZ{fJnEyEwQJ#(0z zI^D7B6zu7aaS4MNcM?1%OeeSW@SES2@z!*!@viN6csb5Hp~!S_#K)vv?GK&H4)1=d zusXq@@zD+egG{iYWj!CJJQ#)B&S`PT{1)ZityekcR~y#(Hsd{;c3%=}={S&oj@gkv zJYzm=Xyt7K$WNhM3Eja##$3h|dx*IBbbX#FKFdm#!hJTkq0oj^+LOT8^ND zKXnj(enfA-dB~5SL012mA^H(nYR>xFubyNuK|Yp^Q2hcJtQ>&Kt<096ML&myem5%x zJ&a8J@GSAWSwDET!Pd_wEIq`hJKfKR?!)xqbq-*4=J@+_%>eL~l$VTA?LF-$Jv7y~ zEMPBb**C4O)#&Bx1COy53>tk1B68;We!y-q$B$p1yz%a#`1 zxBU@?Pa1UkJ^SGh?+3G|oa0t`G%6X$Z}s;2gvmyoX54qpTV&^BwdBHMqrly6W1s3D z?l@+rk>B#Jo2z$x-Wt`bCZ^AYaS?k97wq<9%k!S_8qbV*vTddHosU6Xo@}zQFc7UU zn=mf*$;nx#BpqAsnKz*KEArXvInLwSZ%IDq_UiJccGVA>cgcA$K(VX0&-s3KONT$~ zEZp{>mQ&O5=F>^zS`4qN#kSmgTGceP(e6usaNY!NcDWPDpEc}&a)l_*VNM6}w9G5_ z?ObT=k>`$whC42c9_{(&c@yIo&&v;!TiuCGUVfZO?Yip8-P*qNTLa^}_O=~YvMBe> z{I)&=msoFS4Vkfok#M$m$06dj(kn|-FTtt@Sxot|k{8#ThW@4NvWJX&wa@_r_Z8`QZ~b=RE} z4|?2Cod~7AE*akVVq8vo&F#*UcjaV+F`U}c>~q^sB(HO3MNH`+NGYj&d~e3l5!9tE zXO>Y1$B!84x2RKx`ya(;`y^9W3{pie%e#C^I^Jox2WRE=g_j=gczis6?J0NvH9mGL zZiTMzz5P{)|F*ks0}uGgpKYGmV!~0{y=4x@vlH4jp6co=C<=QpWyzy=MjO_je4d7a}7{ky$x@SckmIJ_^ z!HcJqMMadf49E%*omyq(;nC^!@~7bytvgI zOCFRryOF%n$JI=hx!f?>#9(Ka850AyoE*CEZU(f93>ja3BXp&IZ->D0S*LdR2#&{e zZCx~|>4vx^rcK+JTpw|})8c8_W`j!Pe#Uan%s&)$^KwGHR$ThvcVNzo{!ij(5360b zb8cz#k2m+4ow$qNzxA$$GM=||9RB{~=^KL#&JXcC@@|&pOxr$fVy1b-*sab^I@g!d zE2Pt{iCdSF!dmS~@BErfKR4`Suc_x>Kk|9}YN_J>nE9jP&*(QAe#|diFU&$V^Mpa+ zU9+7dJGvBjeAv6HBK2vD1)iq+25e1;2p*OEsIOSyFkR1sGidCEom~xm&MXmBY|WZ! zlNn&rt@GqepM=+2c}=+^a#$f3UYzuC>BYFL%=}nTBnow{I4ju|vTkOuUf+PKoAjra z=j=Y0k9JN|^SQYrScF=^JLBd&{n7ZBuykzhpGzp;vh= z`n5k}v=OA@dDsgzK1nrelbK<$X~@!VTx#68{s*Lte`Nj84vmLS9jPCRVra2NKF(sW zabB-qs^e!))A|X=b_%-+hP;d2-*z2b)Q}Pe$D9 zdybpFH}z}}rj2Bb@bQk_H)-+(*Ms=G`=1Ruxrw%H?%794!xrzjQ63ya_sOePMNH}^ z+|+6Ov}^Nw&3D*7bJ^W1ukZFbf97ewkLHg1?pT^m-`>5`o|?-p%~DD}^jNrb6>ad| ziX}(%-&}3kqR+VA6P6}yox7vesF8>E_o=uXa;-4igk=F!^7nhy-D7;(s^N8GwPreyo z;*q7bW}(=9X)(Vz*|x9}ug$d`bNa@RHC=~=L^qkWyD|$l*PU88p)cFy_U(Bg?=D;| zX_k>Su+@s88Ps*@^NU-&_e@bNFxPV*lJcfcn=rwJQJ$ZJiXRlM?&Yv%)2poeSJ3Hs;)oHtKC&0*QSB<9kyY_A?p6e8_E^3FbC$ENH(a3ebEOO1pXywBoG{!dnZw3&2&`l@P| zmVx`Oc!^gm>J{W4)NSi+86KY>d~E8x>RV}dd#@&E49@R-BC7I0-@q{zG{zw3Ye_{} zAz5cvwn%fW8t+2vnbz0V1Ff2Om=TXG{nnJ^}qG~1I)r&%g48X#R`hWIp#g5#rpF%xb3*!jaI{>RV<+{ zSa#y(vJRD9+VNbDyZSOy`W$UJq&jHHf`p>TN8@=zT{;`3A6__^CA01Fd|QvF-Pbjd zl&wsk5MXP(Zt6i{PVDIyty`I-jaxvTJBi;bDKL^%&|-h!$DZ9RsLuB7ikV~g>>qmJ zTAx7g882SRG6R|no`h|(%MEoY4f`w{9e23pXz$SSC)*hvm36TXK8%QY)$(;~U&EQ% zLv5G7{IJ$im}SZ`$Q5lK?Nexzb!~RsA8rrt9AUfa?RuGK)!J9#{&_^!(z;jSFwpaRrscZU|tT=LKVnLhz)P1B5jwUDi9(sOag?Xil`3m0HfR|hCm)*3C=6ssCZD5U6>)0{J*Pb_@$}wBX**M|6e$KM7k1abj z$(S!b?T|US%JOpSW2AVO-Zq}8eJw&~+;4NDvo*(H>3Z6n#s}NJeYW@VqjthY5&G}q zCEha@T)t}gFSYoJk*b zEzjuwOaZ5J?+SwmdZvxfuxTxwcja{pJ`s0#!3=EYs;p(pXIabIW?Md6jY}L`U0BMx zbmq?D7guI3bGPf#a*Lna(bldHpN5;P7}_fe(SpB*kdsdUM4dVS!=h;E6y;@Zok?UruvEy=zKA+2cKX88osxZT@=-=AE=YPImmZr_b&Z?3Me zH8j84R2YO;38aw;Xc)dFDi^^p44}d*>6Lf1drp{MZbKp4W>*Zp3ls#^x>-AMlyFY_ohv zRLrN<3&xF;DH3md9NgTvai(~7*cO9THrtM`4!11G+Mr+zS>trLU(>MxFBdj(+tl0Y zY54-Z=Bh)>ZrId#wCK3rINiK+bcIeq$Y)Sfi zr#v~=`J3(RFJTQo!z-FIn&I|DoZ7fS>-kf#VoK$xx`WP!qG1(%$>Yl!Gxy%zV@&qj zlkC-L-c0ktyyFEcAKc!s#pjTd+;5&m))~*EM`C+l9(s50$Sm;6cs{{o?cj4Z`o}Xq ztbwPuaTDX2kc*;y8n&o z&XA7-T8oOp<_?#>HurzKZvurmuG{U1v2J5G9U72!%`U%*N%KH-5n^W9BXS5eei|ZOMS-MVJN-3I3QWtddD@}*-Mhx7YtuiHeJ&lGiaK4 z#W^bGmh4l(!hwlTLW5POs~KKLTeK}X=-sV!_JR?tEtP{yg?@HMMuv`Iid$D#ne%ST z_*K5g@_7d*#D%X8O)=g6B6w~7y~-t~Yfn2~e^U3b`@NSrquZQHUOjH*)pu>^{@eTS zxD%T`XtarS9u|Li-uTlQTY}at-@NxCTY0q0&Z;(ptJV(PubA3x<#x*s&i$g!zf-A7 z?rht(u|>wl=Tx6{uIJ)bGo$U-Y&+#4Y_qMFyk#4|xuQ?Pf;+K)244JDo8M~l1I+K= zt~LnC`0WD!c7cDpz`tGKf4mD!02y4CNGxT`m^fF&5Qy0#ri{(!%D8--$3@Te;~a*F zg>!j4v6v^}$)r+_fWwyYg-kx1EfDjhEaE^%Lv9xWG8%NZ(C=ZIGk7=?=lTW+nEt+< zS!@E_XwWSlWbn<=jK6|xnEiER!`#m&jLzT(bmpX_fZoyvr_8qeEcO3n6r|`;2Z*`7gSz!7&S(Q`Tltc43KG%P*KP+wB z=~mxYBFjqAp1J!z_pCh-K9gK^eEh!a3GIjU zhr*jTq5`?kJ&zi#_c>~{d=qcMbT0kT_}34YVcjN4rYx%{ayhHl{zmbvW2J4Tk@QJV zGakO|I6`#h<@$ps3P`X~oz~+6H*CtM@9x`k0{@nFl zl9X)@b#9Ti?rnTqm+8;5yUcU&yu8)-rGJO`L56O^z&{56%1)tdfA-SwtNrNs_WAt;U;W(rukIAWh8gU_H;uN9bDijv-tJ11d6_#qxbs_dPC2l1?Z*$Ft9(B! z+qi`^Pk;ZIPD701o*o`~YR`19Hm{7@=Zc?ID0ijBCYLD}_IR|R?K ztBvlG8nJ&+OQtsloo1=`cp|8|x6a-5PU6v%K6 zkN6cG5tqwAzY)z8vPEnu&SHq95-DHAm2%ipDPJt*2w4(|M8Fg>Bto3YVX@d^HnI9P zWXk@0_2v0<0{jBlTt8oqfXm4gadCmWaD=(YR58(Ll{TV*Kem`D$nK!px zt@=an+m|~0M^;{4j()oG7T?;UpjP?STqK{}m6K3wm)T~1y58#X4*gVlwo^8@T{Ou3 zUgC>up)YJbhYhrHy8qs{{iA-h>*O}rD|gd(7L=IDE*+OH=}VGlj7=F^F5OwuCbiqR zRhL&-=3x78?JK^y^W~6~w|X0L;*$)F4%b>;qD;xzJL%}-++;C}vVKVgNjd1EUUiCv zag{~L=al6R2k(EB^lcn{j44`wW4X`d+m@2Zq5Tdo^uCZ<7Qjs|`y+6~Y^QCTg5E|< zqYtidSo)dnJF50tGsm*f>E+Db(>%JATIrWZ*KMA3!THeAM?KTdu4-o|8W|p5Tagnp z{oMS5X*ZrdQ(2v;xmjr2ds<!p!|jcxdg-2l4mz zzJk{~E}sdVmzJ~pwsmP4Z@|ful=rWh(UT9a`nYCR(aN)3&SsBH9~*EjHs9>s(8IK? zIo3)~XHndfPu$qaz5aOmQF40trIp^ML5th9794!|;O>}L@f}vRcByaR)dMc) z*1l|?wqbskkDiqqiPv}h=z!68EAMZW`K>b8zg}g&th^#7ha=&OajsY(;Ba|TE{D%$ zNZA}Am&0JO`M8kB#u-Asn86iEB{*LyWe7Pu5tq*tvxPhsQysu>$dvv0%FAMQ4)Eo6 z_VMTY2jCo>g@XFT%B#D~&>#f8nVx2VUL2m5mgbqJRLJDXQakjVHUON~93`x+tE;=B zp;wU6{Sam&;!Vs}MCuH%2+&)`F&O|P06-D|qyhkX>tqH132rXD-ZwXx=Ek6xAARPzPB zEFQh#oZ!F(fR@_=fM)2bxziF=zccf&OWZ5*w5V0JNi2|KX#5&>Q%N6Z!`iCGHLU_sak6(IiIsR|b@Z z{bxqgQZt%#X{uP6orZoH@t-lUXdb1frliruijh80f3u^CIdiA4NU>m z1@%WyC%?W9jU=G0hYEnSoA|h6=za(j1IR~~M*XXsSUscqVGIt=Np<@!3#mSfA$qi2 z6)cxY87;rdMy}6B6Q-oAq{`0HOsDU1QR;J1LgY~~-!r6FpFuxGo}4UIexF7EOBQuY z-)AxSk|jZ?6edVL>N!EO#h{i(tfheODo`tjAdW1%F z3ycVj4s*k^aJ-&J%ddG%mZz)Gpv%+J6pCatR}o{aHO!!EYY1T)0pydw(7|Dbp@YLw zf-PgD4MeSm=oRs3=A(KBCX0pQ+0$#g+Sd%C`T;~Gb{ueriZ#pEhH9)9~3NB7o=qoVnL-q4{C{Zj3{V9458Yj zqUw;oBgVzD1YE4BQ^)Gy`je^3eOt4cUTB?d$#oP=Qz!ld?t zd@{VKZUN?gu7FQ=1xhYpdbxn1x=CNNMM7+mQH^O>KcG5x2OzpZMt!kCeCziE>P8Bv z*)i07L0ur}@=r{JJWcC*(9bXwa(jltqUE8muR0WN`G(bVVbBjS)CSR25^9M0Ck-K% z5s#FwcqH2Yy6f7hNDO46FjXu|NY)HyJDtI#>kKCG${PS;FxzYHBV(wg(X`Og$QWvA zWDK=+(sb@ylF)ti2w=nr=xO?Dh`I?{Q4&)@SCkZHAe}|8FWIkeOnpfzAs|$OggR}& z38ZtlT)b=jKzo;VCqxaC!@e$LftsTlsI3SYHHW^SN{mq@3@%RRF!^}@TgNnf2qM2HzFse;FL4 z8rq`Y4-OR-MUx&$3k?qMOQT4keq55KTT+i1NM|t6u47=bSdu1GC5mMUTHCK(iIMHs zuChVI3LV0%S6F16AQxz4#E4N=I=!<{B@7d)6464Xn~PMRi>l3nX6C?Tak>=QHEpZN z`9L4kD%x$J&k&76LUYv27e|fGVI)Un%p5f~OFt`}9w`-59Kp#@fTK6cpdSb#^v(-H zzAsMtx;Ujrm=Cj|!e}v&C{&Cr&y*w~U9&mUu0%~VOrmQOwcS?lX$%Q<&^V=J0C1e>GC)%RXomKwppMp-1Arp{oCSb00B{}vE&#wq0JsDImjU1k09*xtYXEQ^ z04e~W5&&+Z9VZ4b83VWj0Cxdk8U}D10L}rxOblQa1~3}~n1cb##Q^4E0QLZI0st0b z0E;ky#TdX644?=DSc(BG!vL0J04p%U!-iFu+IwD&0j$LU)?onaF@Oyiz(x$97z5aZ z0c^$qwqO8jFo10sz;+B^2L@1r0qn#8c3}Xe7{FNrfO7@_doh507{GoEpuzy)AO>&< z11Q4)&KLk3!2r%1035~CPRvOFI0XPg0JsMLRHy|5s3msiArzni6U_n^O4umjpoEKd zzB~Y$9v@Kxl(Yw+n!6E7L(A!ia-l6Z+G=|P(3pg#`T)=x`2tYeVgP>VXA1~tr86q; zkLFzf&NtqHMP_!je6ir(WQlur34$}^ilpM4|4u?PFko<@B z5w`q?tO!#UL$*FhDh`fcX1=fL>Y3R+Pz;;u*x2c=dLQ}nW#-G5nJ?e#`0qCU z`wag3Y!ICOwf6+U`+|4Qy!Q@mu7lt%-rU1~_wnEN%j1Xm@d*FDf&V^-|2~iZz7zy! zzM0_LUpp0?3I6)2;LJC_f}c75JHUTW0L3A`eHH)VZ~{30Oz>1T^go0jKZ5`M5dQm7 z{P&0P-ygw$UkidWKVc!vZTt&i*Sc|yI@4y>~my52CyahWYSH*6+t@sj_WV?#3z~_TuMS z#73+TFl6SJX7X%UCg~3S)oSn$(*ZFoil;Lf5iDvnxW-J-EK}6Q&@gpj^y~8dl^_WI zw0xfqg5X!=J2vXSEZ?EQ>+iqwBHCfgPwP~0`d=&u!OW@PbnyPY-MLf2=^tJ^6U?6q zP9OZ{e$t0-0$4xtl^{6%n|r6=wGoR8Q1IFe z`!hu+PX?uWQ{}@{ana?p`)JUO%6LgV-425DAK=H-0P6p`0~tIwb5O?&7@w>Mqp=>B z!-3*t)oL}}Px34!8r#lt#ZVN0>_#nQ%VZ>#T-PgEx}EGS5y;+)Tf?*?Kz~?Xtj8ty zxti|(=~2K*yEU-CQV)B`xVsr0s+HZiv!`xlxndNlb;2J(t`>KC*;dq3J8^kCEy_oO z?viRaKY+~d)BtmtsMq6$eq{`7m}d1)f1IY7>}%8S3dVU2Bf||a4G2rBQTG&3f4Jtw zFONd(kU_H^%oCHrVm%qG)scXH=uH0yme;(guL0Jd`c^%>C!G4{MC*3|N+KX{B4D43 zVA0UKeE3W8!QW-J&7Z<%9J~EN$qo|AqueNfB$_t0q0b9*ho^*HOL6(;V%-Hz+ocx8=ScKVQ@_}sy+I9Qv9-QWX3K$09*jgJPw zsqYMeQy&Wgc;!yPh=JWFcGK9^!|aWnJx-TnM-Pt-;3gqUdo1{y&hQ=!+pDu5#zu?0 zQ4nh|YoB?69JL|J!AlD%eg-o6%nw5#!&X7k{uh1^;Cn%v-A@K09Q7CxLEVY-a;B3T zmjo;f_~7rKJ+(If-rybh=+1oTbP$~W4Kn5gr+@tK|Apk+g5dPuO#f8!KG}cjwd%}^ zF9pH*x!tlHEY6_ig;qD&NzhNLll5oxr2#Awk@5Jo`Bo?Iy&MFy!Kt783!nU#pZh<5 zRydoO(BgMTIe!C(LT@7w-YZ~eyPr#DvK`px7o|I+{Vi+^U~wT~H@kf9-Gm;Cnv&>979c zU;bx*>B47jKKbph|BGM!pPqcj|8nV9|I8Qe7C-t2UqAQJ|L5=i$_IKEKl<>e|M?q# z{ljN|>F<5l58ZDpeC^x++OMts*#Gsjzww{%eDtOHzww9u_mBO;&wPCFTYvUv|Brw2 zJwLnt4{rb8fAb&QT7T`gUSIlCKXv26kM+L&AOGXO^H=`Ye{|`|&d>bH-_2fsf8%SD zJLx~U^hZAP-%p&}1lvoD>)`GdRRL-nzr`o=#@zwv?J{_S7? z&_90pJO7<)@4<`Rmo9(j-~N|B^7Fs?@qhBKc7OTr-~8!6@yC|V1p!ZD5tmSCj8hiW zjt~BRuW;-OK|sz>%9H@E{UC)bRNZInTGh6}Uz3LL_t%28`HvH)euprfFxsiJ!8-_J zAO`!kAUFjEeNPaa{`?DI#^B705Do0kdO!FFwhUr6gniH=P89SpJpKd7=I~wk_TBjJ zd!)d5G!s$?1_>ExOJ_eC1n1w^i=!fL@)CXqF%jvobMy6;`^1uvWpO`Bh{o~J9wq#R zGX+U9Kl?&ppkYby0vh^oCr$^=-QGdJIoQp&n%&O+S5D(Od4h^0`*hOjWy3B=`^6wQ z|2=ETUY^~3wDM|Af$NCL_+Zg52Q7fp>c^-C38wYKxG2a~c=@6DR5k_o5Q+Lb#IF7h z2bunkaq90d>FDq9sp#)N{sO*}r;$V?L?dQLopC4OY!IB@eyf+f90VV0kU`RZU=RN2 z%AI?UZr-}H{9v_t`+jq|+Xdu=>|+~$!EOBeUe;be{=D19A<+%wlP~^D3wFR>hIa$` zOK#(h_x#0gY2)wl8~>4a+xYjm6Z*2-_$Ocf_x>xl^>>T&_qvTwf8d|$JrsS8Y5W7& zi^WCOLnKFsbZV_|Ab<-W{QYAbN%A!;<%lf#5Q{U~bm`3(xZ>Mcyq(6%2I;o+GK|NI z*oXzE5y67R3ij-CVrGUU>LT>yBUtu7f@Qz^ksvtzwGWe4L7^+O)Kga!Fy(<7ifUDC(bUJ8P1^8Js#6a>HV4KDNbmxADtEa5-?5{JX#Q!btg{=2hql6>>$ zP6gj4U@Vq#QNmV_$hy5CIDKyMN0MF;oPK}zM-uFG0b(E7f=>m(sCEjq{3SFI2Z8$1 z*@<&!Cl-5IC+dl6kI)JASS@}z+e-0ubLre!DG)yytmhs3`&QD6QQUt57o2@^Gs*El zg{)MDcq7}L&qYajE6dS}^Yr%i!`(Pt?G<= zZk)#oFuxt@%@XaaumOTDL|@tZpFlY!u8QuaJ= zM7`$q5WR*|RCeNV1vqL9sN)?oiV{w{aW6Vl^92vHh)cn*sx~mlleBb(*G6jq1I<)A z8(Vhi+}Vl8i-Tb~(tHKJA{*wNc#}Y+;skr%slrSUYYI>rBupfRf)_OJlMPJ)E!EJ) zr)bQeyB&29K3{{bcxzfEl<9SmD%?da5?U z&CPI0Z7`4(0N$j&Oy3p?jR0+H0-;u)S){;V0#%wvZ2(x}zMrD=355^Bo7rmT?ICUze!O+_b!hZn%Z6EkR7Mcpn>QiH0ZLE@stGAqhl8Ezup zr5a!tF049PTE=Nvw1rbO>p8qfeKj1>DRr05ojnFhku*2xqZB(qx*s9IY@T z6>3G_7_Qu`Y4v0S8q*-LfM!rn;<04og+YWH{UAjA-S%NzsA1k~ zPd3>6{fHhv%6kwrGoiZ-lIY=XFx3WhH7w%1?bk2jTn(b4ILPv@|LT5J6spKOO$1R@ z1)DzzrD$b8st;I*uv=kf0SvN7Afw8Y4O`u6K3tcCCFH5?miCwLdyiIP-{&f^ zbFLQK{iQ!nTI`#D`;U_r3*{OH_CHy#!oCM8>>PC1Uwp}~eEBeiGVw;7tH+D9HW*gG zjs=vtHcUHdZ1O9QxSpzx;BOGjg#)&Wy`HSIc0E%;5{9rpQUI_#^)MgQf4 zxE$sf#5uH1XegWwpHfl5MO*;NLDJb{7$+MPvi=I{ zPbq0@z05Z^msGV2Kwa&F;qjV8Q)oQO%gv`M?iDdsE1_Q+IZtncfI+K7r%a-i_Nd6L zQ|Rfrvx_<5Ks5|5XoPli;uC^;+;AuLc%o9_RH)`?-F9W*04v(w9pShFBgPB=v(!YL!e)GVOsi|PW!D5~j83ghWh zl7+wXK`jfvTg$@Pxu&dax6`B)&yFh_|NKAvI?2XA`Op6?l8rDnKsKJLmyI8-Z4k2Z z;DZygh$?iIm|g!lHU!Ad+;~18#QkhPR%JenmnsXgdJ~>sZ$(~BrGn^gq8`sdJzkuU zwjab;CbkSGQ{{dd@4|jXa*veUMQ2Y<&1e)Ema@WtKw^M@79ATkby^ zbXOkSxy3{EUwWnvt_4|O9}|!)pxre?wN;2I3DsL~v6SD+vK}obs!bh<0M|q~|8&Vx zYzM-RZ&d%}j8#~$T9YO`7Zs&lv6CdF+B(D@awpEoa?(<3(O#^IVIHgaNz^HOhpOC7 z3YDd?*T!ThV+^NMQmA4#J4jnHyWWt1P9BP`pdP#SDjdwqQW-6Zs2^AjWx1}-5gT^~ zc{aewq&AwJc7PWXk@KV-#&Z|9w>wey($?(k{G}@kbF;ITJ5h9TA)1??i{|IMSL16} zW@ooAZf{-dY+t=Jzdbu2U75WaMVGplE?>TE(Ck@KTu#Bh#r>^oXoZLNGX<&4@)@fmNZWp zBuTs0vZt*F+PtG04wvd09Fb8FyK6pdtdrJB&*b~v_&{xH`=ancjhRynjD;hq@L_9- z`2ArxlX9&Vt)*0Eba*)na*yaCtB8F(6s}}>3^}O83V)JN#-_8W;W#Q4FE2!`UyB3PN#j(qaF5ohrrX*QN z_3Y@!u8p7AafG9+wVe2I%zI+U8iwQAtT5DYGjl3&ZOvPsne~)wNif38qr&3hYt0*3 zS^wg0CaYYMrCJQ&qsib|d2fgyw|~QVow!ZJ`>dQ-Cw<3>nB_iecf#ov2}9e1rn9ue z_|iN`%H3>OHamImTO)&rP{^Luu=*pGq=v)s_*ukQ0#=_S1;o1H;xUhFnR|jHhf_m@ z$Ap-rO{4X-RUI*pn9>|~86)=X@Cy^?^P&T7=nWjX-N-++kxoE2iPN$T=b45BjN{3Y z6FJaEtKEiE=CR^!wWmRw<&<4(8Vc=Ra{yqyQ!Ml>PhEE$&4Ii7o+KxbQ>(4QmU13& z6>K<-TZ-#&;{-F;u@9(@qMfO0TE|Y6%;i{Rmm0KWE;R;OFXskW}Q?97nOq8}GUv=g@{TMBDr!^F#OXR56M}o)YKB3*_fO< zq=8AvrQQBLCZWl_SujC)B4Y-(!i+*vYxeEqaGeSBP- zK5k|QDeM8NvwZ(Tq3%npscZcBhyV1ClJVpIcYmFXABe7i@#9Rr@#8zkGzs&^3#TX4 zE45B$^LYi+_7>>}V?S?6844RKlRfny8#SCHukBU+D36{&8L$DK0E4;B0g z*lq47U1&RWpo2wLR~3V(6Qj~{x2q!6Pda(Fep7X#ylVhCNcNJJ?v~)elbN+B9Y(#y zbv{RMGb#1}f^3Jl(L+W>2})uwC>8SS7*p0iCtDyzqi(m)b2)N~YX za`1t=8N;`yvR+qpg{^63*~8@TKxrxk8Pwj}p~Ra**^r6BDhNE2J=yS>hUiLbZedz= z^8^p*G)UI##<@C3^0*fl1=)En&%XBhSCyHNLPa@|?Esz@Ii*y@gD8*6ScSSOOidK@ z-ck>DVF^kK0wlzI9z^@`yeXk}qe5-PajLq>e$tJ*pyebjGu5R^ol>_|EOPzkS2|fg zBJ*X$^J< zpDNq)v-20{7s%eKVQHrZ;innV~dLvpS`sOID2^~8mb9u8V%$`V+W=;Rszw#+ztP<~(*fQBAS z!?GU^F*V#NaH^9rMX__apLOFlO*DCm{1Y{qsvqXB8!XH5@?Ryx=V z-Hxmc7c%RF4cJ|}s~8JbR>|9=Vb<#lEWa&vFIADcID2s#t|r)Tqmou1jlX_$C{C!P zC<%pFn~Fi)Nw$-?>yh;N5UM%hi>)=JiG0^bv?lTat%)qJAt%*v;Hn1aZ<~ zFIVL_%}0fX14LBf2UUlf@fSbr@1{JyX2o(*=?Zws%C^>37xiyC;YMqso<-C?9F&Un zYgApy28VgFvsq0%Gm#DJUmsQswBv!IRLCb=b*j@_K_ zH=k6b60AC5tYd7FV&opPZZr+#)@BZo@=l1UO?JrG}ryL`oY?!Z=)V zv|5(fQ>IZ5(=m2vngnHBnx3C~P(~Da?mFEIg6zT*7<`F5D?3PdQ3TavY);N>xE5bL zw$U2S#8rsK=!|T@e7Ktw!j#*Q2}Sn2qbDM(b7whf!8N`LNXCp(?U4+&Ni6;qy*lB-V4nIL6I95E& zHq@!I(ejMC0-mKWiaxJZjK?vj@j;Z^2yOe5s)45!rF zDx}5txf^J!FzWTfDfNBd=K=6oX*uYQT1Mhp=U}|h&OsWuGq-SSTvxMGS~6mE;u|6_ zDwb5Id2tWb*uzEyQCpF(rurO)E_CAgct%P=aG~3RL)~0ro3d(z_uM#sqysl>fI4)B zG3p}rn?i_O)kR!cd)(HXO^xd|l{PK)1KH=>YR*Nr4Ov;w`f<4ngeQeM$g^}u!3eDm zvtjPeK|yhk7?N>4@F4(-kkC(g5+A^KjV8@0W%fl)WBW-PlEQfWG)raa_Pt)0IDay% z)N5i+?aJHfWt~0ZFC5rcn`2&<2~L36#fWC8MmF=Z?E*0BX{pG=|!x_R~RKu2JJS&rf!+$u zDSV4pba8X2L{QHo^a-+t6<&vnPo1X1khT-?bbvP~eKJ=q!N5rvi^fNXo1 zcJRZMHJN&o;+?CD&9lf2A`KgpSTpJ|=~gfTiGP-jfekry?JqUu^cII2;JpQzXV!`x zbrKYCxUNxdoUmaX8AUotOEpZhEs6KlN~J{qngW_boO!u~Fj5IyZs;L$m=zT4Ms*)$ zLa_MMr`C?Wm4Zwxq6$!)ADb-fdf>Af6Uf4BQ4NMYR-GUOY%Ymzd&z4+i}bN7$wv4^ z9vm$n8&I6;SlBHD2Z@y%?l9S)B;({}j^aGG(eT;$ZDAI1la)1t=g{-8yY`e8j-lPY zu#eE!G*&T^PmyXpO&v8>UFRVU;+3*)mXf|})f_aB!gr1v4t=%xR@)qSrOodlYW-9y~pU_=Y zH?y=Z(Zw+@uvtP7z?&Ih;zvCGE2`#IumDpI! zCh(465Dh_qO*U*h_x9sFPr5j|Wyq5DQ&Xeh;NS)NxmWHYJd@WuH3@(0w4&rJ(bB~_gIcOQ=5@O(e$=?Lo2e!$sIG$t@>0f8 zS50aUS6*~l@j;gNTitjDw@J+0T)pw=wbpLg?@dtECI^&Gp+ha!dfCnnk_JMZAZJ+7 zX7M-8z45@>{kWgyhwLR4OP_Y|KVm+ValL&tCq){oQ-<#m`*3k{)J*19yzN zsg>QRL`%)N+1Z853v&yz*Jdv-U=ZQOOBXNBE?m5L3H2t_qXLedgqXaDQ#w^-g7@iZ zq&+$vo;9%iPM!@1m|Klp-SNZSJdV2PdSO;~06Tylb+ZE}(qT4KyAckwWFkmF^e__Q z>{6+cZlNYYq0|q4o}U7+Sx!eXX{S}R)N6pEP*Ja!9iSt!#Tc>BLmSHtYu3LY|OrEaM_k z!QkroKz9u6!)#}#XKA6E6wy{MR>fg|E9(`QbeD_^2bXS_#pjZ8cU|gK1n)!fg{)+~ zEWbzDe032E|IHXa@Y@5VMY_p%b6I~zGT6Up89m$I_0Axq3x}OzAf`L=)MX`vra;q0lt6rAwG~v#fRygvSq&w3fv$&TH z5S(d8Kw-(T9IR6z*9V?K5~3qi5_OVWd0GvseRHt(G%9kd_tH+Rni}W~zoJ5gSwVAi z$k7ZuZu<=WLN%GB#u-KKDORc1d7)fG5!=O*YPfHfrdo;u%(8;ZSP+tJ741h!k7xz^ zu}&UGWn2j82+2Tz!%VbY#)z>YE9YdglV*8bs4s12c_(IMe2F;R{~#pDD+4YERpD>c zJBSVo=}`AK4OKNIA&?DA>5$`^1V^e_-)wDjDoa`S1Q2&$(;}AAyk;X>V&(M* z)4cgBl3twR_+GJ>45q5>>H4lVy}tgs`fPkS3TCm3$8PtI{dx?*C^5E*=B+AJREb`8 zt#*f@H`h1_a7-?Llu+0Z`4ydfIraF>0^pEk=_qi_L65&U?{es5YnJDt@ju-wwY}+vvtd zt2@)8uu97IrX&AEC#cJ)HVUpBi+lJQckxD)7X<9_1Fh6#=bcH$h9fJL)G9o9y?Yb< zA+kj_Iwqb^djK`IT*KoSyCnt3FwS{K&HVcQQR$U(qY0kiW?^5b+K!T5++Acp`D#v9 zOnnA~labi0W8HY4*5S5l$XC#pf1b7*??2$oB~na&p=8Z;9fk8T2YSTP^5D^3I@)6o z^o*h()O;lJh1@mv<)?>yoO)yw5{^ay9)s6|q+9N)ew6RUx!MRFpzCo?$8P9k)`TjO z9mJs>#3XyL8$1;Ahh3N1E~OXngIz4OI)nk{GJbzvpWTJwSZuzRW@r0_HWGe>Tl6h# zzwr$nQuvV(!y#ziH5*L-*mzi z{Z!4WxvMB{D|F-i8(EZd5R5+C;OBnY!h1U0;P#}&w5j7zGl7QPY^B1=Fkj9)yS9#( zW6F){uIp}Pm}@MVPQ3=?paTzZ!tS*^8@TUUK#ZkDMvdXa!R?4W+Ii=iG{hP*=B+k( zIInrP?WE8W_GCk-Q_wYNKFpjKymK-4iD3QIc8ny2wa7>+X!~^BSEWd4>-uFa9+)g` zb{hL;ElHD`Q5io>`tf=h^%1`S!j~PkV#o{S7|=-%bbf1tx^47MwnO%IY3n9MPt(~^ z7%Id=V2j@_$hRQR9pI4Uam=gN;`07*>o$X{@%vg_F6X!qI_Xe%m8PoiECfRP2rkua zS&hUX-+i_9Al^@OCN!B|RM}dO^CarsrPH33=C%)V4@ZM+`G~D<1c94#tjLM;l{mwAY<5V0vmY8iXyli+;4c^GSiLlk~ z^|~V{tv$@G;d4wW&hTH0OMWqe>(!zY4dPo_{vh62ed1KX%1aJ-=h;dxj#6yWN$9AXZo`adeil6~ zgNmFkUdv;UyDn|huQ(6amOt8_d%^8vdZKKv9 zfR#*pY@DuLLp~G{@*OzuQOzxL#H)Gt9k~N;W%;`GoR)k$Z=bJDA1{K3pq#cMEOokMw{vz zm^+qt;LCMea=4Ty)jF^kL)4e3@Q z=K0r@B)w$7R(KiFZW+51mcwi_3Fzxv^H;g2TUfGer!7($vQLRPCW=4DUQ>{j> ziarvdt);0~N=?4`)C5X0`B&eEMNG?PxcFwc7axX;Ax=z?FPXkST{11`^pBENcT9s% zr=(mh#ZLOeK)$wkUv@CzlzRMF$(;fwg1$n|J8>DR&CRDGZ^*nhB5ypCB5AJSl$Jr9 zDCrnD-UL{_1Pzx|MW&KP1Y+%(o0L^MTymw5IoqxCE`(Fh--C!I+mR6u^_GHX#|}@L z^b;H=kX+>mW;E}U)YVB#T}C2t%jdVns0*#r+tC`0!0=Gb zei*zcX5YuEQ7u3RCP>(LtEz;BGY~!$BQ5AyV*`ZN8)$2Y?(J^b7^-+#b>3iu$VWXn zo?O53xgN?6yWuSRx0(HsA62tIzCTq@dG%DBNKC>4z4n^dWqEu?4n~Nt=m(fT11#AC z96LevRmD_LeJyNz>tF;s54I#8kKc`S%AS;wYGSSPpR-9o`Wks9Y%%V&V@&XX@by<` zV7@U!IK=POFH-xiwjKkmRW(2p+lkjMUe;nQH2@=F92@ zIRV-xlMN}9{u^Y}an}_3XsHe$#QSTvhjs1;b0(EO?xLwbbxmqNRkcMS{LLj%^!)ZT zGt*K;uItKj#d6n_b0%Mhl>jK+Ol6jJ5%S#IGIl1%6tGjJ3!oE23%0&yTrDe25!*t; zHwSyr>ghNZcg&rP!O>GzcC$h&BwGzgkwsXPHgzH878{Gt8v@r_kTXo@)(Y`p^Bp@7 zV%FAdG!RV+BZ?BiJi%Ar*n0F-*Ks9R^@Y2PI_0g(;yiShV)wDH7I<$)v;zJ1ezMg| zIvk)I7f{B4d;Qj$*Yu3LZ?(hFf9PH`Xj}4Z(^l;2D^tvq;}=gYu}`peO40SSKOh;9 z_6KAU@=P9Lys$E2bWbG}XzZX1xd{czt{s;OU(X6kbGaDWAW9Bx*+{X8m24T6Ea!5J ze6j&Bo7Y1uNHEnRGb^7EH(55S9U{gMMHj;{)#=<9HFVP6aaUT@p|r5abiTqR-M-z* zHC-zez8>XWEE$VcjJSA&%pkG2NLzoGZR*ikt&Ek!)Ya}}%C~S_x5RIlKeJ4unwfz5 zsY7AQe5135n`By*QkYyu(Mj8PS$L$65z+t-xrRYRWwFrxGbDP9^&^~Y2w&oAsvg4R zPe7djL8^gBLaIlosB6w5M80Y3{0OO734>8n&KI}AZ!LJzS`|9W$}a8c1y1k#&3Y*h z49@MGS40SKCce)Yu+>PC3YAtgX-6LqoukYK8l@@~Mig2am#?0WDy_D`y5Zf@ z%JGQ$JJOq-NB*`UN}xg>DNcbaw-*&YGpIW9K>$ip;yx70_mGq~@+97-*r-~8;}S6D zMOOMyN!}Dh@ab*bChVoGAJLXfY3gdY&Ooh!6+&2KO%X+%*3bIFFvmh0!wOsHwI0#I z92dB~8tSoH%+oF|1?|P@PPyBDtQxu?UY2}!+nm}|^RsG`LRZ`2@{N_7tG8Zz{q|=* zduQ$Lz5Cz)VEy5vH$M0IANav&tJ96QcXpF6@Adj=Huy?jl*9dlCx>61ots~{c;`^T-Z`x1SO#N8kZ;dxf1e=lFeD4Po?45H0+{`g_&d=Bd1- zQJWw=g#0DxXx!_Uvn@ALnIleZ1|I^RMuY~e-Xy`js7-;Wcq=vx$2_PhW)kn4*TX@C zco3rewhEK3OD9LR@1;U&CEa#Si<`0u<9($r0Ex)C%zD{Q0{w_WQpG}wT>#?wDw_qR z2_I8wU95H{b*O@I$+GuV5+u0!^%`CozF-Q7vKtS-fVO@LvD{9Po2Mb!cbI_gU`7Rug{N;hr7I;cH^`ZRak>)^!WREjKkie6m3e-B)p-9w~#1{h%@s&OWK;MgCGQuZ95LQepEt z>um%mJBpZpc>E6!2k|{zj-x5M!4uX-IE;WQ(KA$f7G9xQ(B3#gbH#8{8FNwQ-iV)ND5J>k#aQn!SsKwA6m5Jov;0`e z6`4HSli>yc;jB<$Ivh1fiNK)isvTk!7SuE$?Swjg8$McinN)kC%8i1+dpx*3-yH~O z2h5=v(ZC>}c(ZUGy@}4~Tj6NPnwXBFsu8MZ*D5_Xb_Ap4YxYss)zw)?{i5BET%5|Y zGOMm!VM?SJ0b8>=y-aDevDXeV<^e5^C)D}#=P6=a2gh=v6Qo-}HjeY>om3qZJ@k56 z4k&6y^O?wtwWveFqJDvQVuXxh?91U|E$Yyr!rtL>x1Xd*QN}ri!dY?XxW$YV_0lWg z*mOVY?8j+0%L}?afP*fyLNTrz)d2jUFszUMib*DmUhhyv4qPD{K&=tqbWt}{6~6Xx zosU#LxEPuYq3Dlnbv}Jr1KkX3^sVMmlH&A4!np*aHozvy^{> zFa;8H6Lf-LKz0ov7YQJR`hcTZbrt8ZPId*Gp*rq|W_;A(Sv|@{oqGUr9E&s7(L0*} zs{xB{T+lbe$*Mah9s{Qp`Vp>y1kGsb-%GQD6y{dkD7O_AvBfH%U>Y|`x9E@;jI)$W z)wb-O`!bUtOc@SS?vR0ClJy+d+8t-O&N4-P)IH6<=xlBYC-UAc;&GO-(ld=v%s4U} zcyuH$K_Lyd0~`2{koeK?vS_QL<2U9gc4OZ0C2_LF9b6R*=WzH`NYP=lanqO|f-fjV z2XZo~!4Q^Tb^E@gi|I;wh9b@p>Mqm41kPgA&iXLFbJ291ZnAfV_-C!}TTdd{v+Zxn$Yalim?JTo$YNqXB- z;i6E6=x$^QH#H}9>rFK;*~|%k(};XAdp$GT0`{zh58exR7p!9(fsfJlMjLWq(F2rf zo4jF^)_scNA|5$8AwX4nS}(=C=iAR@CXi8A-#`Btk->1GAkvFU&(n4FMq^%0yG&Q~ zvO-sPhkbrYM0Zh79`|EF*4i%5$=zY!2}vcip_ybHgaGH|E2uxE zq^~6d0YCn|d0JTa(5uyITSVtqO5EQ?1*hBC}2*$CX|; zd0K@UnK`7ROv*zC=W{+&h17vtM|7~G>HwTjF4>`e@PPF= z>PK@Ry)#?cJK4?>3w#4}C@)1`_yd9+hDSspQcRuRJ{`6vSVDb*vnZ*sZe5W(Lqd$TrrIHpdUdh@6prYmoC@vQ_wZac|-oa*+i?cW-8TrmXd(ihzv zIVX-*_N}-d=ft<;XexZ`E$d*0smTR=uaV$gYTX77}TP#b^ zoY>9WiLG?!T#SJXDfR*$znivyCx#^elAT1gj)36&piUDPWN9+8sHMUSlrzgDHnf&1 zf!4K1YKg(}HSvq7ZjhH7Cg5+R6F@Tnsy{=$3Qbn@bd7Km_623Dp~tF~n|a z9ZTxgK#nbe47W<}@c(PMGISI{TQNY5)acB^RifakO-plP$^@B44QEo6Da8cs810W# zWyF4~H7HD*BUDc^Q6{b}yugY0@_3LH2`(Eyuf#BGOpIlw`g`aAd6Vq{YHym1tRVgD zWJ_6id;P&{?7;i{T+KB!{ILWpyC*22Ivs;IZn{mPtXs74(UQWdc=*s7h0nh>I#V_w zwZ-bp4yBzh&YnYi%DI^ zg?w2!g=LwhaK-zm#*I&d)0()yqgYve)mtT*5QZ*<%yJ!BUGcR2JAsT?lPOVC&Mq$@^5ChrNS>ho^4*+ zdf8+i64o6*B%=c; zPpi>Ob5(K?^;6#t_60Ev;0g2((|ASySc^)etTVxE#_*wy8hWktR0DtU7dr~D17pJ& z+)O&qw;SAVmirfNnx}M$9seXnbk?z_X;VCPI6`(-RC|1TH&cBKwYpAiXT#Kqtk9^m z0-7;gV=D5-dDI+v1)+R0xCxyE-VnhLIf<6S1K*LeBVsL`6B5}6&*gdpyT zp7}7mrD&eRyYT_G-Ruh!M~c!xoFoW6rQ3-j_c);T3>hd=ZmX;hh8j&4WfkSB9`AL> zW8)JGg=94yU$tfnpsm+lt0Nkz_f}G@*=}rTn^(>k27rVQdfcLVR;0sy2 zEEMDNc-ayoxw`BtnR zzxFTzP&BNjb1lh@vZU2sbFC+`;#QX@Cmw!8cDl=~-Qq8INxM(u1AUPc+i(~T8;4Qp z*Id`AGiGN8X`Gv1k{mbmGZy2V8`cTBSJbj9&622Vgcq7IX6TW#o;T>O54}GcVPLNH zAVxlSuIos9dCLc3ai|W9vEZ|MVwy#?p`AvBxjk0~N*Qa6Dd=YM@j{^l3fEUnuMzezBmrnm)D7}hY?$kGSctweZLsYGMRE5T#B4XV zy8~oXm;Hesc6j`r+1Wfi`}X-HF;_;Bbanl447-}=ut>`ll~X3Hk1RXNMyXq-v{WLe zNgS&&Q~KNC7kpB8ldc=m;1GLtE7}6t?UZobNyi<))(Q7W=WDB1#n4?__y{%JL zkGnCFtO&(w-PhcvTs?WCud8$htZ#XIdotYE*djEVap53l)Q|CyUSj8H1(`D`EcE&tWWA(w$Yza1Rp-j3Lua-K6~(YmhV~Q881H-HVpeQ z_2KM>TyI1L-3jTs<}2fJ2ykS*c4U}o(%wFLM57+9jx@_^z?jC>WJ5#U(g!hFG8!R` z9P%W>4JY3;6?V_859mc&9Ql=1F~ z1`9Bo2cR0k$w@OTI~caSah6eaarWZKdRlv41s}s&8ih4-5?HKgPDe>f&+0>0sbSRJ zVZVRa!r8|RS4c@l07^pgsfskLs9j>Y6v!NWoP1Db@j7zR``5a1k%^>-bAuYVy4@gu z#_;%Zw~HW}-B>euKT3x#~Wnrrym2+>u3ftkCiyKNdpXbuw(Q-!Qv(^4_)wv7s;KHanKKra+dS zqC-&NoYQE1sVckJ33X7woX48!_)*Jd1}ZS!(M!3Vcbw1^e8wSz$*DSNgM^X*=&c7r z^)E^ShGW>?j>BX6J6X0@s9v%cJ2nfWa>FL#tU$Z~iPvr)N#50@4ooO^$aX>Hm14UQVKH(GKx$Ejm}8lwOk4VXesEXFX zxL3q&Z)x?$?89a@zchLc=nZd%Nki0FL*MjtZoj6v785(h@g$)|Ss$Q-Um zJ_$Y@2UrUfe{$UHMz{_*PE~{j%;(~9l;{v|M3KMgEo3_kPlRQB%nB-lx>c8I6RgL+GYjO80w!po070$M1 zv6Uka+xRV=B?(WqlN2HuUPs_;3}BHyG7vu&m_Ht5Efr3ygWUuYuAtD%eq5@pL);S& zvsY0@Jysc8W298=xM7^GPRe($(kNJcfdWnf17vaq@A7sb?iF zJt)nMzW2*j7cfJ_cHMua0S=-bVdXkN+Aerd>Bd}z*sX_*XeX=1N1IHCsECV(-|A=GshO64un8ZD z4RD-rp7~Lj+H=;>Gy0E*?78qp4as%|v93(60x}XewLT8Q){xr!RTw#+^Kl3f#SzXMJBPj)kJ7LPU5H^dpdZM|fH`&7_J_mG!!D zuKU)O93dX2l9A@bJ^X47H15E4AcL)sWSD%57ZLDCn239m7nNXbjH}(rc2@YJGgR=m1&O6=FFjnl1ureM+1%wqyY8LsJ$9$MN zHbj{YXsx_cdzRJ;x^K-{gU;Ku0?a}lF70fY*{H>+6SJfp><$A6iBMiJ1T@)JbwWws z^lEf2xysEr?a`(IqwXxqq_uR-C&zH9q_P6{_r#0RwC59tCmS!A2Ms5P_wIPXP=)39%+Dvz63$XVh` z5vv~9Sur%@rIqzggj?1o>${aKvbxktD=4D17_aLGsNG06QfY9}ac}(Yh&}GelX=qj zQ4;St##EV0`XDJr-Nl|N91M%yL6U}wE@_8xJgBx zd6MqN2L(|fOB23TJ*^xdk+36Cnny@RWE)}BzBH1AUgK0eEm~S_S$&d}_fo$9S2dhp zFy26e^v=TK4~QOJ`aPNOyHBGW~+ zmh9zOne5HbOzCSCn%B+!KqOg?`Qw%$bhjb~vhDut>O8ayl!KPWG zD%y%EOl^(8VsedYSg4#{UmzEF5XR`vKdrf)e+vwxq-j$-ztMm_g*C4iw{^^ld5!24 zVhatyV-T91v+Cv0_47yC9A(onhbEY+5mF&B==9pmneakwEOtGENLJr)Z|${*_g5w5 zCHHbaJ5Z8K891X(J*z7{nVX%j?Wo{_T!I*5HXB!VbjkVAY_e`E$D;il1ads$`MgR9=La%2Oq0DQfrYB+e%Aq z7$h;NyC&4jU{PMrzm1~P3GeXHwRk*I&EUc`L&%`sn_5!4?J>U)kYO`)6?I}Hei1(9 z{8~yUKhjpVa+rHrvT3w(cdDkwy3AMRHiNsv{#NWP`n7^g&MNUm1`vD{4=#ehrcd(3 zrn)$P?c%k|SLUx>0`^@Y{2)rZS^s9-i$)GN;eva=9U^9-phsy^@>@=lrnQJ#pygp@ zq}-gmTU-7-|7N~N-*(bv(6lLLA;|ZG;+*-~^5@kYxxy;V)BKlNTEvoCxkRIr4Qd-{ zc`ddYG@206;&8ESvM|DjeRs*PiN`CSkU;*lp9gsVk9W0fREL0CHJh4`iA zGQHO9sriyO4LQq7o?e-7k6ozl>XW48%iJnr6EE(4)}hFX+@wqdqA&Oq%lPC*o%+=b zaaGkp=+-}%MZ_zhATBZL75WlxmU4D4Bt~e03v_JTC&Fb(MsH^o?jvcdkk0Blt4*ly zQVEqr7QyF>-8e_eQ*Da#VNlW)Ok@D}^DIDOir z-mX!pDOy`4DZaPJttDx4Gb&@S+=hf z35Tnia}a~`T7w}7Xl!fO=jI(|UsIEfHLR@jn#nD&E_x@S2fm^jYg1}YEogKRyPNqq zJUl!c2j8qS9dp&`=yu1?<3*?9rE103Uw11KWz8xzufY?N>-R@WEhuGj-Abtfr(z8; zQCpXlx@y`Ip*H!rfpLOSAA@k{Z@0^TUw@td_WS&|D4biBAY0v}A{7y6PWKz-apYVs zYTI?4KpfdPk!Fgv?nfox+^l6??Uu?c+GgCwspNxGZrJVwHCqe#}|vk*Pprh;%Bp*o>@gMsNsPug>{RKZmNWo0rqnbQ*f zSo(6#Wx+4(q>O+zQ8}mKK(3x0)=}%RC_@as43uU=kSpW*q*|~H?Jcv~*%~iGE^%}{rWEvzb7~q`_X=kHPEQA& zTQk541J+EYRx_l&XP$V_znM77xR7g-)1qoP%&HkOel+!3>}Q(vbOfsbIL;#*LZ9Su z2g!LBRoGGu=}#!$z`*DA2yD!fE~Z(F#PrRCih0Pb?Yq@#NkCRNi#a4Kev%XvHEuR8 zU>DwSxve*^%S}X-WmJPM3!UvuR2>|Jy{QX{ilPxpT8j3LDbp0}{{{vo38pH~-OBu~ z&k#tHM>_rc86Q|U3L18FIWE?ENQ8z&o>&%=EIH54LGO}+wv!&NXJ}c8>rs!8Iz+8> zWD9!qqYHj32?#nc(~q=n2nbnf^<;3seQk+i&(or6NemT*y71L1!G^qmq8iE~=sdz= zo!uud-6qlDNr()+)xvWufe}FC=xc4SMm}N5K0-K+U)nLMs@Nh4c(ib@-2}0iTHAZr zA8Z$f0gM(=T_N=1@~}U+MM+n?NwMdys6{U;+a)yyL%e(ysV?h_G1cAT6=lv-wxtla zOp60|X2J@w2!VsWTCShmI33CT%D^Nzpix9yy|_EA;xyXoRgZmghx95|+$Z4^ADUfK zmHioZ-dXat-LK?vL?L>>lFGITB@B?`Eak;3Bskfgt;YDq8APO!s7Et3(d%RE_T(5xq}@u0fe*8;=A zh2Rf5%V!$)0IUVYuK!VwuPvkH-yx^^acRyIe*h%Utb&2DttZ*Tjp%_|EL7CKV`uFc z=?nrU;oyv1RB=EiRN+ygec@7}MUh8?)%g;EPNU}2wRCfpt1a-5H0~@J9wXM5KTjf) z$!rdxgL=2EwN*;lZ+;dp?e<--@~bDTEO*etQWtf~`2WB8uFMGa1&bB+Y`vru z4K?aLFKSZl7J@EqA!GdZ3VjYKmTe(pPt=9TU!c=_kx+44x3a~|Gy})vW4EDI-?R+D zYYdxEsOVLni@3kNm6$f-af3uEdvISp;rWIMT%Cd!ckf9 zJ+VWA$7#>93UtB(96vuS~R{f zDQP`p$8|D0rmg_5g%sNL(C*l`4b$)2PC6G6csypV-9RJJB1pM0!)YXjltNa$wH7c+S+wBTez)F zs1lbj9Ax=kLGh44M;xUH)g2<+NG~blJnE?|)k)p?%Iw{^hzpl1Dt!r|c$BU!RWcY4 zlQk!(%q+4%VN$j*K^b)xb-(V{kJj>y>Uy%cN1Wjy|`iVbHTGP_QU; zuSI5oL}#OYjPQJFflVi8aSuJyj85A0+4#_0qD=Udl!&G~jVSA;W=U%*hHY{@+Hz)3 zgqyyMC@|&W?W}FXAjLGmkc~D00;q$+kMuD;dM#sW`A)8ONX*K59$}ID!&AZ??Qh)j zqy~*vVAGCK0i}a)ZUK{p$cDMsl;z9FED$`4S}<{|Ox#piAIZ~aG0i;4 z#7m@_>l-x7f+h_<3hEF~MJ4!Ll+#t;P6?wAj1ft-TWfhJ0rC&CyTiT}VCR7{fdr1b zjg9Ur8yhYBnVgJzgWc$@t+AukgWdeSncj+a%$h;NDiWizN@=6 zE4(1Ps`Ro@Xt>}*LlBr@D1TgeYqy(&sIwRC#4{X8OuKkFEgE;5`dm!q=r@xdAs?F( zEG+JxWbBTUZoYwwbX01xKogokX8ATe-E^r`s82P8D&*s{?2dIkwz6-q(T^9@WK=4| zOP8t`#2o}xo8wVYFDVbF#+XYz`S`ex_hYBI>9DdOpcK!K6cdT;$5H{n1p@GhW@vVgYvs~$t>m3! z+qhC`LpV$`8q2t&reoY7Wl=?#CSiQa=ENkl95EeCf_8}m{v3YhbE|i<&R&(9B_WOF zXHtG$hK9LzEs`{Q^&Vprcr`x@c3$q8W$8KAHVf;$yc>)Cxq{S68KL*AMD8t_KVdKk zl4@zA!ZFtTw)G)oAd3KKUYG9V@cr0sj;dMdlG*+<+13i(&ZH%*(b{BIMun{1FmYjb3h`KTS2dg2Wgy}Ws&bBM&LdnsE@*$ z#fw#)wK6X)h+V^*dYW|Z7|DQe{}p0&g+b+yVHPStK)Xn}UEE6YqLf}NATq3@CWx_0 z8NVF9G8&dt8=q`>kA?obbLE)YH93*66#$drl^AW`7zD)p9j;LhHrPLpM#8Lo{mJw?d}xt z!65pxd6Id#ZT2eT=0pg21gT^`91eI`j(bxR(NUt|Xo;zj_8b`V*D%elwZhTenz>^< z7Hd=0RjksfRuowIOnT;STdcwQ^- ziq(}Jm$X5?8b8j(?v>;)KviZjtPQhV>$Xk?&D~6cK#~Hd_|qhH^4uK_1k(mD zY8H;`NS;;$pvxDvs9MYNSe2vz6sp{fQVoy5EE&#pPr%+Za>&Ice9#W&*kV&z(Hzyu zC_t)CVX3>gsH(Y)EYWL+!YD}P6qkIG!O=j~Ws%enzfx2Wq@gQUHQn238Rz>Ea`tMH zol*1pARDh+78R+HC(R%G=W`M!+GOBKq@gczvu{x;pW%j+u9N z;tl^1P!4=e9)KRQ-q`7ILJU*CbC56GaFT&wq4n-59y^Yc(66_ejbM%-#8po)k6ZC9 z<>ajveq!#BfPj;U#BiM_y9S=w*>21&seW7((N5fM%rB{4lJ2z|3rngH|Hk2?G(iRr3Vo}hCDNz5 z=oE~xWD91r$BbIm554$R{gC@AR-cr4#HCp}%5ya-OLQ1*MV(<0w!@8Evm4iLZ7g5e zSe8S!3f7+}?>FfX2#T!EZ(O~#abs2oEx}Kd9nkgX@_Kn?*2t8dD*<|M7=oe zM!D_#+QP=wOV0be+eCO?b1Qq|6uPo;b-@C+r~(_tF~M( z8+HZUYgad}&e=D4Rv^?W*O<6=bK~lYc^yZ2xodmBy0UTgrg^!Yy^vLzWVn#bMIau+vlTr@a?P;wA*apRh$E6CR-?uu$A>0WaX6HrXQ*Dh{cy=59f z$eYv1!p1c_DgA5<#5LH>QWw~TjT;t0I)R2qRd&*gPEr(EPV9rpS=qQcZ~87edDiQB zRj)Z!`$;c8Y!0HlL}H!hcGPj8SiZDz!xFia#UHmQdc3-EW7+n|Z5|{k!q=!t#!{K3 zJ42`WYgau`22sA(i=9z8GhYnixU<{bih8{)bMZXCvFwbdG!(jgbK{zwZ3)w=lAu#y zHz{LW6}*4gFN%(=ZK{hn zi|W}=*WuKOdir#VOX$tni_O_NXa1HqZrm`quA%s9g{wC=uG-0|t1vg)TyT20y6TFy zDx=gie{DXLbI$ITZBo*~U{&MQ?1;UP7e|NP5G_*n@?O$suvHU9idHD>G@R{)Y+5B+ zinoyR3|h5bwE!5S8#mZULk*g|DVze6waI}R%j)W_jT=|N)0lF9DZQ2D?iy_u(;7vh zK#Y_0;4Pp0%v+Vc_jSQ2-ZJmD3>%y^U}+>&^hq5CG_ONC*cYYGy<*fzI2@>66Ks3q)(_Ptn`1TnPRte{bLQbunmn1mnX!hY zixV7_*55Oc(`X2uM|p2Gr6gt*^+!7uotPt@3&$X#opsjOp!bJ-i|My}3pgcBQ$ zPki5n$*E7iGQGI;YWw=9KK*!OWAh7Ndh@NPZ|k$#qBsq=3iYN6KQX%uFXbm@Z_=On zS^hJ}f9Cnm0{^+le=hN#%lyZzV)O|=F@KexU*kXA`uq+4wL*Uu_~8OST#$zhz``mQ zF>9VQdyxUV#C0xlol9Kj64$xRMXqp>D_rCX7rC-(B+Kv8S#?IMb{d<27r3YjeQKR1 zf7H96D}e^wFff=oP#>~nxCKEXCAD{93^(v0c}rGhJqg5AN7QbA#oZXy-Pt1ucQtupS#J9*T{rS*Q+juBg@ej)|{E$nX>w}!pm;YyaK zaR(cB)0@b79~ckkw+q-+)(_JTKQ{Ie4}1_3?a6)XJw5WmJ{z{ZlT?xsj*LgcR5KF& zY9+$Wcw@%$05-n6<-m@~0gP+b24n&d*TSp4lW94a>GYB~ElFGABQaeXp+1<7WhKGZc62{9@p&`vWMo!A}ctz+z%nuoFWpm~F& z=IUs$mvrK^;Lx$n=Jl`_@5ep9KP-*F5Hor&+2VJX|3)c;)p63cx6Vl`Mcyu3ok%_ZePjLbFT)Cd-Ch;xUc{YZ48E zUB>X4_WnLre)Yj{tCw_|QMa4N1%mmB<&uFn))C4T(IE2ZSVnUNv@>rb7^Fc+7DJ1| z^P+cBs_{JP#M_YKFosfFx^)4DP5?|O9C1RBbXnl^T%>3dM29rx6bz*!yaRIs4ntQ+qJqt6MvIhXm^BW%1rE0goA;7WLf%to0B$k21tcGa+W_B-tb4dP+QV90?q*%v zhNPpAHfR)bOd=en-FQ1m<1QhFG=5pw$Xt%WFvjHRNG3|}ZJo2lD^T6gNUOefA`j^p zt5fsK&v+bHH#k~D@->_?(=i$1K8iN!Q>NsUj=yo+mT9bOoL|*9Pq!@gsYF{0 z#@r8A()Qv_CLEe`CQp6jev*%3Qf5z_PJ!cu$Xa|R^j)(0Xsw119qS|ZBoZ90hF2Hs zDsdu+<$^?{B9_yulILJ_lTQuOWU~-wsP(aHHEDWB?oi;@2OcrGE#zTQu zC6^A((B;?NqHGSLa@Wc3@eEg8I&x!EJ)Kff(WFBhG|~xgNk%~NHUtQh57Hb?zWG=+ zwuufmpPHL^>r{LZ$u9p-hVDRt7_-j#WcS!5A&wrYrXuy2|VM=vEOj<9?R zQ^YXuwI^K~#@LB~;RJJlC@t%??t1k%zev!wjFMzR6jNaczgRE2reOJdvkbYp9AL z+1HI3)<_QQJ@sQ|25kEYu|cfEe3NI^uIGbuTh zORcnW)zO!pH_z~M?(Br*6j!V1ev)S??yppxUL55u^{7BT7fE8jn(j+f-a{PO2wS4G za!PXh))+8&D!bW({%X2^gz1PI;6D3}6gprE30vYA?6EOxGL;-UoIuZAOt;eOo6wZ8MtLz-pu>;YKAYBC|iW{x1FFe!tol?R#Af(;U zn4$0@+Ss@0>kwu-*fM#I8to1#Z^rh-VWPS_E6GQjf!StkGX~)2f(2RaXx2%S(<6O$ zV01eMSq#ktksjXwrz3P-%EQPsc05o)OX|k8!&p(J8}%^gTQhCxEt@U40C;N7nN|4?3Ka`E~4)#lGpkt6uV~(3|!&` zX0#S1D3-fdIHj>p&-_>|emUEsxPwi77t4f#<*~#i+`~>ME{g48Phnp{iMH^V7-w2# zIqt<{}+bns4420^eF1gF2Z_fttP2u^Q(=-*9F1@D~x`b$C34}vqN zz7hnde{=6tuoDF5-$VDSYzM*lZ*!W7gW&u(h}!ZjD_i|^*lBG=oxS0J7U*%x1la~~ zcT1iX_Tm-@MR)H?n{vA4MYg9rM5{}IDq367-b^32&U|qz+WTT&M4z6UZ7tBhx!KlW zxCNb3TVldvibBH742!KfzZ{wYl7p`Y8maHsNRw!l9z)ZDB`@olfN1S!Kok!J`?cg1?T%q zK@hCT^Y=R6&jdm6MS1=cr%-oo{^cO}#UOZZ@J?_xc<0nhL2xEGjsMOD!I_VITM(Ri z`P=dHRPfH3Q!fO;nUB86KZElxZkK}(2Jg_{XKd*Ov~=ILbZ~G$Egc*jtW{ycXvV|z z(hEUw`aeA#1h%oF*rmpbVt1smqX+n2H1@I3Z7doj)L1k~zF38f8+#AHd+$*&oallwE6;UJ*N{dxJm^kNYF%&E2c4`D`L4uaE| zFZBPy|I6N+fVXj7_u|7v5=rfnWy|t5q8G?EL2wZ%61HQ5Bt*jEW&o5dJ2pH3hQLUJ z8E9reijL#NZ5HRHO`N5PUz)~F6DQ8zG<$539X>EVIaZmU>~qQ|)9Uc?p8lz7CUI4(B<>{s@%?u^_b;!#?w@wte#z#MKl|m@ukC$a>76g>y5W+) z$X@aOKYIQA`lfGwP&#u%i9bWe48$t83&JUV6{O6JLD&pYHtIKV9s4@vlGp%ICKXeeG9& zaz=mWKRntswf_h0_58+*#y!~gh-#~+)V{`Rhy z&;M^_viY{3-#gNN=PRX4UVg)Se*5m@zr5uG_dWl**MD&E_+!6)!6#~S_x_)Y9{OoK zsoXie;}>VW;*P&L^R+*E+besofBt=c88k8L*u*r86EmnM3WJ%<{J@E!lk=C4Up|tb zUW{FS`Is?v{pjrB#f6iFL}Gq^X;xA8qlwwY@J_@!n4Na^X89R<t7f`+<*K`6t?zZ|{gr?OE6Q zwX^^3_?{Ph@r8f?>t8?h%Jz|4zk9~JM&A14*Zk(@FQ?!C@;|=vK=0G9-&lTe_n-g# zW@C0>i^=+ulV!NN5ApqmMt%R zUu)ajzR>sfpH%6v^pttw+~On0 zHZ1J?>JR?r>U%zN=%Vxg{(b8%yRCEY@o#5##|NOk4P2YR}@PYq2bj8Om zE&kU7pS|vZKl;np{q~<;P@d{N`+e_?j=XW=wimtg3+=zT`uojWFW5qs*}Q2jDi+*7 zyon&{ny#;iES5dE8OQlK$u~essfq-$*_2(Q|v! z-CtFAAAy?sz=Ycr{nFZpG~~5zF#mfxLxVE9KLdh(~A`l<#FH_}zn?G~sM}D`Z@Vmbn{mAsX-MK^Oe80K% z!eZLFv}xjx|895RL$Ca+i+_0J*skWs?oqn$c+KwrBRzi3hTA`yy6f?)V82rCdFZyc zPQE|>mVx)bJ;dgHP@q_>It=nGq z{h7s~!e#&K3i#a@7!K_%j|cr$(-N&*SF74{N%CP+~!B$eBV3Y za^MXwdhqQ(eePF2I{bsh58QUsyE7?spZbAY-teDSY7c#&W9gh6?1z?r1%4{5u<- zRzCbl|C71Yf!}owf8sNDyx^9X%{~9$9>2VA!#i&Mej$7FZ|!5>>9{N*NzxtC_xpRt zYF{Zm_KS62zE8d9>PrR+U+(St_E&%Y;Sas(x&z04^}1Ij4m|meKl|D@Keh9>z3adC z)vZs?|MP(xZe478_mx|^2VeK_ZRIareCzK<|8C-&w=e$I{P?ARe*Kd@d%pd@@BWk8 zOYV{X^1SIs#?se}#{Qvt@%dvv-T&#=J@lQoJ@ASP|7~z~$9I}v|Eo{_uLpmN8u8R{ zV$XXAOYb=UoBdyZ#lByB<7V}JN)A`Od$d zeey5Pe&t_%_Njvh=KEi}>npFg>yCf=$A`aqU3(^@%zp4CFBolo_dEaf-&IwTq!;e$ zd*ATGpL)&(nckMm_a6REcb~Q4wJ#ky zdUwYou^&G2$iIB=y;r>XsrUT#gEwyb+~tpdZu0V`mp%FuEeF0naA4~EyS{b9Yj6JCpU=PK7vFYXzwcX>GO$B0 zTzd5JJ3jM@ZyY^!;y=zw|H&uH5B&P^zv%nBCr-Sl{JbZwKY9DBU-0dB|J7}ue5uy; z#!YY7(lv0$HM7S)_1sIE9*Fh6_VrIa@~WxY^Pc~v)QjF)*nQ3qF8<-io{(-jaKlI5 zb;Snh`|CgQWjTKPOTQq$Y2W4xKlaFz6E8XYNa40`?CIL^i%;BB_~5rwZ(B(H?H%_) z8;T$LS}AdBkMqVq{p5RFpZkRTv8&oHG9Ula*V^9tRQz(0zKZuY73NI>Iysl-~;FH?#6vJmnAg%2z$@hq9p#*bi9wP44!$u<~2oY1{BdG`m5b_}@;7DQ`kzc*UP%uh7NfHC?3k`wr*Ll@~ z_P|(NNZJEqL4O}azo+_$REC7F<|be|K$3t8P%AF2qjJKY0!_w1@nLnWE{xPFe}0)+FshbBLu#w3?fUhZ1wZ#d=glHBvkU&fq`^G2qd~7#jcSF~xsB8b z-`mjIlt2b=0$vo>%ZZv+IBu&Bq=y-MjHHL}$E2w~O_J_!k~(nCwvO}9ziy}R$+;44 zI}8Ahz9WbUh*4WUrm0)vUn?$OMvVF@*5ieO;RQR+f$H`0Nfi%UYNYEkTlSg+hArT z31~)oh@=5x`WPt_h~a1CH*BZ3ku(4^za+nRN|JOJ`3>9dKa=#ZNM+KmGbKs-5Aysh zNs=xgZ2(}h$?vlzNve`^00M3y?LP;`iabA8lB6Xc{2>8BuN(oERpAzNRspg@;f3)($nNO z5bzht?@M7W33gou$}iH+%Oy#=mGr$!lB7KO4V%MZlDAuur0O`gN1xRd+_ z`rAYL(kDsMgXB3t=ZDD{?w2HKlI%JIk|bS5#(xmzg`_zkNzyqa?+}zp>K&FO=^f;G z96$gFL6W2^BuN@0NF_^{_lk`yQ9Tn%GK%DG08q|cMzAdhsC-y@PF zog(FoN|N+7@_bB^q_fCxK=9v@GGUW)$nSAUl91dhNfK-^pCIW|uo}s4P*grjejkE$ zLGn&YlJp+Z7f@P$jHH>CBo_Hr__|!qVTn`No22IErSdR%-U974Uj!dM=Yqj^$?3sqxfw z2I(M4=Dnl^tzeY_Io6FON9M-GBv+6m+m&KPGphRin-n+~RD zrnAZEvD{qR)xt|i&bF#)J0(j6o#)>5v*QypnXFjDewq%fjPi<&Mr-5jOeQ;?PG)jr zBanC-8P+aZ*i|Ig#zGl9)GKOlUq4i^on;h9z?c01$=;3$vu2@MH?zzz6oK{9@i;S( zga)Ar9kX*Ilc`bfco0t4*W!*$ax|UH<_;x~io?=Fhb3jqYlh}5LD5@BX2y=@GN~Jq zxyjU23XNkMost2PBe-b;X!tRuLOm=SBSX?7PW^a1ac45g^xADUQe0F z@`_!SqXjr`uR2jMKf&H8aQsQ1km${FbV;TIcS4W$4o1=cG&|Z4sf%XexN1dJ!?BjC zre-+ZcA2G@J3C-JcHu-YBDAD)C5ulY(a1w2CT_C!a$-^F(lcXDM@X= zJ9X;RS>z33;NgiF_QBWMUgf8i;T4u3UaI^)@S?Y)s)p-R%mKQ9ws2Yx@ z=yoJ7M-V2)(cef%QMC(JT#h8r7F4s;Nicx0Wkq%@WkJ>DJe)y;l~lECI;MQgtXcTj zKQAlQs;(7Kkc>zN99_p{an?J`s-u}kT<)kUB{eQbU89gNByKB0$JwfYotRdOHM5eAsd^MI`r(> zxFT_x?rUT^@Xi!Q;RCpNvK;a4N5YWP5g8(s(fC-hE-W{g1BmeAi)w!P;iOnd#s%!X z6r&iIZzEk^JJ3cI3Kp;&XVzqi(0K^lHkKbpd0Db#BOS&-MBs221n<3@#2o}Sv)y5! zeJ-#u!d8OV0nmF~eVSVdY?PbCWwmGBstQ|qCBKxfLEqLu*lLzK3E$ZYR}et0t+V4P zBzUyrmK2Li0cqyEX*e(0gcP!jm)wBV>{^L&f$OnLDzJS`5@qa?gt5Ekf&j*@Njm6Z znGj=lk#1wgPS=duN!X)RE5;fva9+G84KX&&4KX%nH?Ia`)0vR-FvQ5NI0K{6QvV=W=9TRTK zunbwrLqJ5tBw1=vD>zWoQUv=8*vK9f66{lKxl${XFO^F*aAJmglsXCH#D+DLYbt3@ zxt0e3n9l+K<>R4%$cx3LI=c?gVO)*?UDEvn$j7WLNv8C#{x2{NujLM%Yz z=8?qcp>#5n&5b3p2_!KA(*jHxmBV)u8X#ZY$7~bnceb*uqchV7Q%IG>GE?Qk`d9&? zj6hXet{)rEjV4AXlDUZ)tkhx2$tls^Rrl(j6O*9ku>>tnr3zXRR>B!EFq(~Z<24hr3c6|V^48=3 zyElni*FbE=R{VCY3V?=o59~$&D379A z(AucHYEv1Ql58VL9ynw^EXPZr4wOgb2%~>kI#;13MNwURi&w{00jo$z?Oq#K;Z-BN z$IIa=SRVK(-6k5N1)RsXQ49|a55>`+hUAC9jRF>1+}nB2?m^^>s2o9SD(>r^Q>n&z z-;kh)S4%u-N%7ri1ED{FjC}zcQQ&05R@BZ2lX209R*^7WK>EDa)7Ue*31n|!M;8U9 zSVV%t8f+O7oIT!;jC<~Hl`a#(t|O*8g&1lKL&OgBUqtC(8^D0EHD+52-c+{cs27W= zJTOiQ1NypDOy&dgO}thO@!-wqEC^1fXPGrR16Hb)eV_>=FMKoPg(KMenOa z*$j`38eLTL0t2>Dc-#<3tZN7)ek6i~s6Yy3#00%jZ(l#>#uOA~09HOZ`^I9sWiCPt zbGYk60nr>WVKiI?{9he`!If)}3c13a)NB;kXB5$h%Cy@QOd`TaL_$GD5F$kt2!>ul ze`t(7aN{bSzz%RB*aRR4MyXVNs!M(ajqlhLCexD({_iR5)^tBd2M!Eb&>Zt{9=nMF$S43vF}WSyU|5 zgHnaEMXTVEO2`vg1`+~QAO!*-8u)+T&=h?%m7I#p5g;7=go0J@{NXe{sc-PWu$#dO zfF?#+aZYy}hv?vG2I73qqbL+O27owcV#M*zBSW6R1~*=5C2V@63cPR7bkMJH@1Qok_-a2-6*<^LwXy$M_Xpw#m%|MTeCE*b!( zTE#yEHf9}q(-019Xo!KiLBs(#h^!gJu7L?UQ;K70CuvC9d9#3djjE+p6id^WATETh zfr(m|3<01O2%%#XWm_#kSO>}#YO6b3A&YLPXL!F$ zs#)>5H{}+VBM!byH@gNFHX>wG1qLCkyKd=ZVzmYxRwyQ#2To^=28bX4`15Ndf;36g zhHdlFnYnas^k6PKb0|3t)o;qqO;0B$@dN1YM%*-Au~fkfO#;j5`;i6F{Y}!%p5?d4 zsTqc<%h9M|MnNbiR#H|CO&2kK0=p(&xbU;+t+$~S+SbqtEsHBu*r}=c(kKe%jidzx z-l*ep7WJn~R^+0hR!jr#6m(?uWYx4)8`kcE;;1q;K9ZfXW!6e%6mdf+MJ<+8u7yA| zj)s-5URnZLnL-M(QkiK(Bz%DJLiGy?LTTY<3gYC0VBsQJW@o82v-qB~{0(Y3z>t|S3mcK<%465M4w<>S6&?R6V|^!l zGkqs#3|64%;DaV`2x5;KLZSACQ0N`vVN(&}wVPFljTkC0TxpoOnhorGMSV`3PQ4&7 z@YaJ0^>7AXsX=aG1)f4d@%0EwsaBVat^BpTuDb9F=}1(oJJO*Qz~+(}TUyFuHRM7f%X@G@Mj z0*QjOw65F)JN=00N)?KUbY;bvoJJHH#OlFo^1%Kd5f%qh((vxOku*>x!xIx~#Cd#D z&k$&k(I2M#f$53Mk)AkdN`M?hnJ)Z|i$?lrw8HSY7hZfE#y1Ld3X7jJU33}!1qlOJsI23(~bT?#al;brpM+|*<505ES=0? z4;b7oX3x+Hkp2`CxJ^nNDO= zGl&(WRSr^B53O>KJ6Ae6p2}qX`KYT3vI*Nl^Kdf@T0Zp}*+8WESL2}ok_)+)h_&vcqdM3-cmQ&3q79v$Nn=+Y z&y;UlGHX^hM$m5986ekAnv1xS(7l;vrXD?8ZtTQ^gRU3439_C=vr>mET!gECd|SsN z05=Q--$?LHK5KX2P7IN)d?I>O(D0y{q7&twH(^7j-Dqet?r3N;KBq-EnsmvQTq-~q zfNqdcm~=j`*jO~TR2{|S1^Ye+Ndc;b&oIFnWJ$ge_vR+LxsgtCw%_B{K;Cy-wpVJ$ z%^*8kkg_d8r;s28Y&--=D9ZCB!T1mn^n>6bL7@kw=73N)nTP-(3GuS0yR%RcTb5*j zN8&QU0kZM3Cb5*TfT5?%EZI#yF<;k17BZC4%Z(UWMc!o#>FE0Ql?|&E62LO{y%ZKD zr136bUwY3Jyt45?vGP9l%1uN9Z>#<>qt?Kj9GCr0u4P7(HjR&MFswF@?>RTwr3n!c2@$iE_Dykmp zi)7@%TTTf89xJ9MH@<{TVF;A;_w)>{z>z1=5RXy`qQW>MQw~hN)8h*%F4Y-h0IC3E zx!CB+rrSljUs-LvQgx|{teMw9?r26fxqwX&R~9=5>sr2|Rp9#SLKL4qblYb4^vrA$ zLCoY>ZZ@5qoJn9Glmcq5?b95j z`^jv@C5V3gtb51)6>f*+lQ{CBtG8r8kq^~naRcy-_sYT z6U3f7aHk%4dfpl%bBEzDkU!_E2H?1XwT8=*W$!xTN9um&FMzVc5PG<;KaTz|^-%;o zRdeXx!CY0fG_wdT?H#aj5dqpHqBKHZ9GACxs2o6JZvZsArw4%fj36Ro8l+pEZ6X6u z=OA!f+p21lie{l=uGMM51_>;YVdOU8deJ0!gMKs@^Hig=Ba=UK9x<_*{5Ai3U9edNs*~!FcGIu1Eoybi>UEEPSH<3)^y(KX_E3mJ$@lr8OwgY#)#;$Z)QVaVH_PL8EA-i&-(Y(ZzWj8Es9 zE#3(?+rFWg&jB9~dPJ6OJL8*T#I=C2`E+#Z+N`7Yqhj51z^CiU0WA{r->36Am+!!| z5Aoi?sG?Uj10Aq87xUKyWfYE$$)wS5VfUup0X>|r>OH(_JR=9X`-Fq#6QhjzS($d<@o(!&$jLHrAhZf!h0iTofI=ilA@R1>;0k+l%+uihck%IbBN z!x403SqNkOA|M2r>O&UGAtDK6qkUZssA82c$blMyp$Vt;k3E?g`d$BQs=ueV|8&Ja zQXv=oD1bo=aofYZF}zD0_bGsXK?xDM5sxpX^zzA;J1GN0+6C(-M3x+UW(ya%4+>%r zt**99)fL-WtCK9z$EpeK1Z+1tPcZhvZ7SHRVin5noeVj=!hX}tf)9La7nbXV zUls(;{Mm�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 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260220/20260220085626-Config.rsc b/MikroNUC/20260220/20260220085626-Config.rsc new file mode 100644 index 0000000..7eae094 --- /dev/null +++ b/MikroNUC/20260220/20260220085626-Config.rsc @@ -0,0 +1,2684 @@ +# 2026-02-20 08:56:25 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-LAN port-cost-mode=short +add disabled=yes name=bridge1 +add disabled=yes name=bridge2 +add disabled=yes name=bridge3 +add disabled=yes name=bridge4 +add name=bridge5 +add name=bridge6 +add name=bridge7 +add name=bridge8 +add name=bridge9 +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add name=WAN +add name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes lan-bridge=Bridge-LAN router-ip=10.30.30.81 +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/interface bridge port +add bridge=Bridge-LAN interface=all +add bridge=Bridge-LAN interface=all +/interface bridge settings +set use-ip-firewall=yes +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface list member +add interface=Bridge-LAN list=LAN +add interface=ether2 list=WAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220085921-Binary.backup b/MikroNUC/20260220/20260220085921-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..73d0ef6f995a73d06319ebd4a71955757f27a7fe GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220085933-Binary.backup b/MikroNUC/20260220/20260220085933-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..3828ebd04c7b6a7b21e5089272297825cd7a0d01 GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220090536-Binary.backup b/MikroNUC/20260220/20260220090536-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..938f6357ffb78593c085931d86e5448be45bb75e GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220103550-Binary.backup b/MikroNUC/20260220/20260220103550-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..e07ba7b9534f57fa06bb8b9df1b6f8c7656738ac GIT binary patch literal 300266 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 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260220/20260220103550-Config.rsc b/MikroNUC/20260220/20260220103550-Config.rsc new file mode 100644 index 0000000..04d0061 --- /dev/null +++ b/MikroNUC/20260220/20260220103550-Config.rsc @@ -0,0 +1,2687 @@ +# 2026-02-20 10:35:49 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-LAN port-cost-mode=short +add disabled=yes name=bridge1 +add disabled=yes name=bridge2 +add disabled=yes name=bridge3 +add disabled=yes name=bridge4 +add name=bridge5 +add name=bridge6 +add name=bridge7 +add name=bridge8 +add name=bridge9 +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add name=WAN +add name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes lan-bridge=Bridge-LAN router-ip=10.30.30.81 +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/interface bridge port +add bridge=Bridge-LAN interface=all +add bridge=Bridge-LAN interface=all +/interface bridge settings +set use-ip-firewall=yes +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface list member +add interface=Bridge-LAN list=LAN +add interface=ether2 list=WAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220130018-Binary.backup b/MikroNUC/20260220/20260220130018-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..8764eaf87c71d8fb6be4d89cb8390266d5267c1e GIT binary patch literal 297833 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⩔_!oeiS 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 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260220/20260220130018-Config.rsc b/MikroNUC/20260220/20260220130018-Config.rsc new file mode 100644 index 0000000..fed65b9 --- /dev/null +++ b/MikroNUC/20260220/20260220130018-Config.rsc @@ -0,0 +1,2681 @@ +# 2026-02-20 13:00:17 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add name=WAN +add name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors=\ + https://reg.vados.ru:5000/:https://reg.vados.ru/ router-ip=10.30.30.81 +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/usb1 registry-url=https://reg.vados.ru/ tmpdir=/tmpfs \ + username=amster-dev +/container mounts +add dst=/cont list=cont src=/usb1 +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface list member +add interface=Bridge-LAN list=LAN +add interface=ether2 list=WAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220132007-Binary.backup b/MikroNUC/20260220/20260220132007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..eaac508722f209aa0bbaa8326df8489457a365ea GIT binary patch literal 298179 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

    tq4d;UJ0cV=_)8Oc_p0ua5fuc zZ|10q2ZVCEa00YZ;I=`~NABta&xqSb(gUs`w`rA+fKECEbRW+em?>^P4bL;G%4j!G zi_IFk7RP)3(_YMzDEH5v_Zd@T+M|aCm&(VlEl(XuO&ppV8XvT^zJbYs*`wv_j_vP5 z_Ts@uKfIYt59{id|M-XJSdls~=->tm*3@8>tA=(@C$G zI>VdGqcWqK&yE|FLP53d)GWHQ?rfedo1V*LlViEDnW;ny8!-?S88uIJYgqZ8UPGFj%No+$ zJiJcO+(hOzT@^0JjD#AF2wMs_9m%Nrd=w5B)uPLPf;%%TmbF3|-YsZF)yD1&0dxpY>vDvp;Bp0{viI(LnJi2XLD~nxN%%9(>nw zZ;@Vh+nbJP_*@J(PvhAEfz9W;rJqiaFKRehhs%CU0V>DAk1F1G`- z0TA;OjSHMS;P?J@!bXSyIZhWOoD9W>>PM}?#$a%L7u`I$K(N&V-oP+0lUCLS0KHJ5 z;I`i!^g3W;C*y!k-8|q7d%L>U^XSoHAP{@kw9UAHZ zClX<6T=9x?&9>J~&SONqlP@~fLHDZbTlt{E0;98k_;egXs4ikNcL;IjmjEo*czt1C zUuN906|p7g1TO|HVtbqSg=&c>+u8PdgMAoAVlR^ zGHaGxEt`fao9N!-JLMj1B=9#Ssm^Grz=lUyoLOD}w?&7;YGN5j_2U&n2Vb@2&E_eQUm? zA|YbUam9rY9kHUhXy~R=RewPbGAjDm$CJxsfchpk;R%7tM&@k7> zO`~Svu#q(!8IlehIHx|_;UIC#eBmJR<8atPjSgbr(F+ex5k4^?SOOyyM}O)%T@jLt zbK(;agdPy$Zw?+jCM4(ES#JP3wv#^a$ztbm=hdAofyzF8I?RLLm)@+Z#^PGB=PeRF zg=wSLro$e+duBE{eIz-OzTTtFf^N6t7Ur#!U>ghLC7k(qGtx63o{1UJqx+0EW(ITM zB9Ti@A9fec&qJCd@L*tk%?`A)=vqF;8p2qc0I~gLL~Mue0C<7p9-r*6kMk(Uj;oHN zS~{;RI$zUuL4fC7YY1;*4dKn#M7*(-qGpET4c7eA>EmFdP_AQ9&6E4{Y;)dOR4i34 zs`Hwm7IDe4r503efxE}EaSg=;!JgkgKpqB#l}3;v(4W*xH-a9L_Ka%jy-9;Kr~*}i zB9UAm;a4;G8!ygo2x1NO9DqP_2m0$Hmf{FO^4K5<;Dn|XmfOXYsi`}xfLB}Glg+@Y zZ{?HiUTr)72ZLCX1ZMLv7F&Tu&)I6hQk~p!6$xQmfL;jKKcZ;LY80&H4m`gF<{-LcK60?jqA*rZ`a!Yb94M{eG17&V>E}c$J zk7EBZT-*#nr7rt~t~qKv7K>ecT(t~U@2*KtXQoo)=|mQLapI)Zr>|K>j$oU{k_QuWliA#40^gBMl2Kcq&B>Z& zR@K;uYUvuvv5n>cgW?-zrp3ak)8vL(#d4x!BWM&-)0u2ydNj#B&D?{ECt?#A5|5`7 zhZETZ_B6(+I1sm>sbfIA3k?rFT#MDJZozW{c>uQ{vpjp;d8)O%t`)EqG2;|B;iowy z%enZ=Gu*l1Y_FJS`I?J)w-$^X3k4X&G)drn?gRb{1?DpESf-&B>==wfw3zP|_)0P| z4Z(hIL$F_L5ll-Oil>R$jVlXfwQw9oeNr@t@}!$3Yz{(sv*+*)g3tsOayjeCB9@S- zn4lGdPUDazpf58G)o@V!%%ZFrvI^HJpwW>FnpLQ2TuX*YrjbpAG=_eY`@=oE2riCn zA%2A!sSQ+Sfvjsdw7_1&?XL-vMB>CHjPkQC_=v>ig(0CEZUf69WXB!CCx3O>aDoq5 z{pf`e+Qg_F5#hj-Si}z@M=|e7hmnGB<-Rbemj-O=!4wL+`lSsoJ|+g-_$)3yU=9c* zJ-E8ULRBl9`dVo`n%R|DEsBoJo6kO&orG}YxuRj`a3DL)C{39~dE8zP)+O4>ls@H%`R%7~*;i`%H^;Hrhj^_JL;j!!;O1 z!}h=0-YQ9Z;T1L4{IgJV&E+i?aI46dYhyxvYG`BXYiMKol_-x8M^Xqy7w${`f$D%qdjkML0^vwvJJmJg*hK&xd-3+=n|W zKHH`0Sa7b#4UKd}YL*_YDoz=8fEa={j+7mI&ViR?=e@#203x0lJnsztc8ATouo6GK z?lhzt|50yMSJx^`R+FR?5Sl8Pa2`o_6QxivYlhPeZRvIvVg+5%Dv+S0I{46%J~8O^W=y4tw7RSfe6(by&F@<|USy$`omN{($ z_N?mK!Ej39IgB(zfVsbKe@{;w|E+iSg+$c2+Y8oz5t;{Kp+FXtke`FG^K&wkA?l-- z{P&<;wx%ber-9o3Gq!3)DHPV~D19AMPxEuKJ>v&)pvzSDXuuKMhLWYsD~94fU^~;F zksh(pO!R=1UXZ5m^6wkc$gnYa>{J6#|_?=FMSvA~?RtwRK% zxZGLPY$dO&Vis9;w2EpM6kP>RFdTbAoF+1eocg+F=`BE(J8N1I zQbeQjINl88Xw*G4viy8+zE0IZLx{O5-`lcQglZv%o9`WPiKC`&T2QN1$}9VNy5zpz z-Y&UsV4zFxz0}vpPGHy|b%GD2e2JXURm-vcscE0t%5(ST`NA09#C{7s>{N@I6WF`X zc@0S9sH#{QN3onK({Re2ak+9e8OT zl?c?pGn#PMRPreHgMaSf z(`h?u)k}B$6EsCA8=b?>lBKFf;E1Ah3yNNY`RoZ8tiXwc&+@feYH|5Ghe9e1XbOh} z`thdn%~7YhpjsCAHKVocD%6v>vt((-Su=>PIsr-g``pV*mOB?a<8t4A-{X^RaKWF> zCEoyh8{h>Y_;eE1CV+lAVKGdoTB!^~+i6#PgWWlAnvM!+?w_nqq%caGi%>M8cyB)_ zf^;Hi%Pz$yXLLCv>PLlblSBW@W9Kv#mlG z@}b4Qv}&$sJLC!aWjjixn$rwhwICh=gjSQE+j$YlKRMKv=Y|m4dG5JDgpc9tx&Rvm%8ZKb;c7|2-;#NuvVq$-{xF!P z%?#+59EkqGz16jf2AlnWpV9UXnfw2q;yNA8(Gg#fF>6*qm7~v*$5h+V45UHv&j` zC=>}j9x#*&ds0o6U29{au5GpDK$apT5~8xc2d+_-UL z=5-A!$6VU2+Fr+D(;if?QuX~=&uTJK(ALOelCo5cGpV1X+E)=K-F@hW5P{&9&=92t z_&*wtBDM+hM5%QyVl9S!T2bFrBbPT%8@bt8mu@CCjpM)iP}jV}1{crhC2xeDetNdMmyq z-F8w0uzzK3GrdOV?UwokmKV%N+a=vZZ*iPXaZ=aXI*Ba`-LP;l1?xQ3|jd^fm zte7b4so_>kwDbhaciX1xv!txKBlKUUsoYF)FC}O@0lpsGOacWX4+c%_aDyg}xw<%g z&RNIUZMZZTCG9QoL+g|ygvWB`8?#JnsUQ( zD)Ap=%p&n9#xZ?Usx*UTj9;l?Ou}&4h%SKxmu?k%L5PMIUKBsX*FK_!j{;q$_?>of zROn507!O#2MT^AAXzc|(Kf?;Y)9ywUV#Tklp|@{JGWRI%F$uV9>77Vccss2oR|kXDI;PQnP!IB(m|#mZ)6wRjR*6U93M5h`j$9D0JY zZs%gfj`l*G0~4~oiq%QB2oFwdhqxag|C_kv#T@ShI6%ZG{!dUdfZY%L+dB4(s@@<> zV!}2_NpVmSJvoWS?YKS@+0+egE8?|H0(B6Fn;JW&fFTYeH(`}1vGhBs-mbX5q_tj0$(=|LSFeLp-l*uh z`Y6>JyJ(3V5cM$>iERlp20}OOAvrB>E}6JLaARS1&7|pK&fSF6y0)-%H8+p1u1qhj zncQeTEauO!xxPF%y*58=&duMLUz-O$U1KpZyGSpQ$a=-XMT1tnt3y4%YQnv;RbV7u zsR=dLf%^|+JB0&eb`nG+sZFOzuB@>|@r}fphpCSE%^f%HSe|=_^ib)3FEGo4?DTDF zI?@TP7SkSg;8c|O;)}}CtqS%b;xEJ%65VH-+;ax5pWKl`bEo0HJqnT^1;IfbuImCk z?>D4;d+1uY?jt1d>|b@pOX}WgmPIw^CGxfEq24ZjGWT0Qcjd*?1{f51?;FBedRMOK zy{H9xpy4MdDuFD-d5~_msWY7HG4ag_fflBZ3tZHmYK+xt`(GRrILNb*U-Z&k7J*r8 zHSb~kWwzK|STA-UWuRr_Dzh=!A7v4=$iQsvS+B${+{EU)fe*S$B1Qy<9g346+-OCX z%{D?7xdAS=@EehEMiZPX8z>bm`1Rb(WlolCpPq?9u}`)fU6(VPW{#+&^}?5u=a*gH z=Z>c7aF8W#X<>h**SqV}Wfm2AC>3OIx-NYK+ zZQLkw{e-n5ybyqW8oyk$V?}PziOuC#RuHu`9x+wzaVI3{Yc_*q%Ulbhi1~@R7Gake z@w+YSJPg_bCovu|7qA-_wZvx3thUGE*xTbZt_HppMZ@Nb<y;DCHdi5at`6Hn5_AP4_|Fy6H1k#cj!_ zNtx%Bw{KOshqSXH4E(rn`t-{5%*?{t;>#QJOEBKfZ7kndzq+urx^ZRU1_eGDkj2wm zErx;n*~bl2Tqk+{F}||kTdgd|toE%?29Te;%pvftAaLDLqWBIG<{IA$;8^=slAITn zeEC_90^bVaI3Qwqt>r~g3%(UdKR_zGF|M`r884Nsavw_7XxZ4txc2l6jSQL7(?WN# zr-kmHXBN7^hZ7s_ev5-8l2k*oUfFA1ZSdcrAo*eknLnJS-Ac5-c3E=+DW4eWzABX0qX^C2Vd2LOuigGtB zsp~4wB|wQhms$6)36VtGKGwik(27hVjXsc}-<$`U2|_kOd6iv}+x4cr zx`~+!XRKB~$rQQzoze!Ly5D}~a0XsxCO>t!u{<>oh?tSjsI4{|QCd>i5NSsTPmnIwZp~Omw z;h?uG+)7HM_q8x9ul&~nI15Vge5`~)IQxe2r%pSnz;$=c+l zULWvLQ{+sBBUo@Q$erYVO~BMK)Pg#EFAU@}gWCKPhrDRQlhS?<7EL}U)Ghnmi##R4 zv|kca2jA&xXoW7{SS*xH9WCA=Zzz3U2CMo$xIs;7x`L*HS*i^yuR%=Tg{ zk-k-=3m3fJIAM(oqk9)>6Bo8yoj0z`%0Vp7zQU&5i?i1z z?W-4Go?U+9%|)kvySX^dSj+9c!w|^%SGvbonO|Kqc~CJisWC=O1dZ*4rtP`d^pg=z z7}*FaV(lPd0!qCqBI;1l54mG!!^|JGWhM@)(|am6`ExjX-+)MFmux$5xvDxM0l2g% z*$)&*6N9L$c&Xuiuv)EQg)WBy3JactLmeO1#R?88LMEy#S-(M9{*j`7F_bWG%OZFe z>4fkRqg?d2l0{mx zugp`tb`JJr@i>+xy{Im_SE@o!}3Dcr@%V; ztb4r-&6s9-lGCoLeqjQN^`^2Jwks*(Y|oTZs67WNDfC;ee_JE(tg4A}dQyWLJ*h#P z16nknjP{&ShK8u#4VYiGRXt&T(lFl=i?+~9^m|Y|aH=_3lTJ$bCxW8V&6y27BMO4V z%nSrQm(J$+=Sa8}$}FWZn5Gx-ose105J4W*(cT6g-i^%*oyet+s#ztJK=!c|lFHEkY4bZ#=t7~EO)F097LWC6sxG6!F;%N&n1Fv0yi3dEKM6)Rkj>TEm4)Rs zI)i{nG%q-T-GM=S1MIsXfw?ayFe`8MfYfGi0r|TJGjs zq2GGTj^nr9jNfwY;H}$j@2%ZnbCW(sUnsJP-45M|#pYPe$)^^Ap$d;#7%#RlR((usFReO6a;XVwptPA}1``)Lyk!J=#@Q zRuCngX)5ntd|Xr^uA-7{T0P56ZZ7*m$YuAk)MC1+&rHg(v_LZ}RU!34jC40VJ7h;a!p7(dVySv$7?!coe z9KU%-1rC}Vm`4Oy)vZX1Kf+vn@|EYYzaNOyyChwJ+mGb_4H#>WS6+I7T0Oi8ffLtta0TKx{bhAu3B zq9J}R2T}5gDs}=7ug*`eytZ_8gPxaIU%3HBoZt!>bW`AYlFnm!BU;s%CAc?DF2%s` zsKl^3zqYopbai!Od3x=dhDP5)NEP3Jil4J1p4zdzZMH{l*O{oEr}g^PPT;H{sKPw} z@I;N;Wbn8D_$#skOqDw=%fVQ~w-VCx;&1F{@jqg`ncD^o3xb83TdBm>4l~DUX5Fmd z0Lo)K%rkeb2$3YgD)FKR&Ifo=@zt2r_6Nr!=D0C-(S@ChRzB?w46T-C9~GU~(~jW9 zo^}L(FJl;GR%CBwj~48`O2jBKn(McQ%`MB`#&vSD%@T{lnD9IQ6}jM~=$;km zj@4_m8d`g7`RW3HPgY?lfmzSPq>IiG1J5z2rJ-LqnX2{RVTD)Z;Q2HKo?D~Nroid) zAsl*W0!Q07ppYS3hQ+V-Br`bT>b>r1*=*F5UvsqrdC+%kOB$cxrtUgtJ5 zJu6|py=S(W6?Y=;ER9FI$Rpdfe3^kOt3kxb3&e5b(6jbr*5%O~4y(G9 zM8-JA8?&{Vdg}|rHj^Zmp|rdu5lzL zDJyb6`CgAZ+6t%^e&yVu9*xDm8!~#j^8twQArgI1;rn^Lnm3? z;PUZ=6nqfx_RY=DtY6j9N}5l~XA}e42I|j+%I2&Hn#XXF_TqSBdv<2@Pk8OwsIwMa zU7DD*Z|!_MXkU7BY@0couPsFWt?S`bduM%g(Y}lp5>D}QvBW7?@#D;|tgiy@>jSn|^wOMi%;RROb z=@3(b;TJuuPxl9(>z)3BeL(?d+{yWp`IborKS1V zZm_Z}$T>APlbsu4gy8W{&@)iI`$pFaf^bL)%CYR{X8R&TIAEFo8~FD!4YuF^(Z zLd!Qc2J54jDEbIJdfz`cqs|s3@mN?AHW*~(8~Okh1c`}Q3|$tbM|_+H)XF#5+tWFbLBy<%#-9DY0={$gA0q(SLZiw zEX?Tj$|KE_R+3ou7S20>^D#P8$3vDI^NTa{a~q5EYu9da;Uro=AzF`Dz+cLp@SdgO zh&j74JvT?Ht}Hep`+pS@qq4Au>NNO#D`cPc!wR<*kO5$j(982;iCNClV=#siV+af% z{4iGn%Gsm3PKV7i>#Uq{rD}-EGwC zBjY2Nhz%mC)GDRj2qMz>XT?pl4UFV|PurKvJ#AmU*sq;aYugw3VoXIp>T8%~9_@H3 zU0%?!;+P?n6|TNQn5f+c*AKexJw!fU<+g)%ZpR@xDbBLsF-R{X(<$swL*|nqq|^eG zRn>+XrX+_S1&e$s0MN{XG&iZmi=r8=3*`^e*mC7D6?0@EH!Ka5ZXzY$prf8zBeH=)-1m2(eoVt-4C`6Ce z8(CVFMgdwTQbW!=7N%WPkf8>-FsTt#u55r9T`%Fim5O0q4i?2Q<>uFHj-tf6U#n+~ zOC|DJ8jWC)M<^Uoduor*nTH;eHhBRkR#F&+ig)|Ze{jDwJEO6^lUqsB8gOQZC0i9M z3@dTqy%*ONbHPgniL0PRX@4cRFCPCkeisqn>Fo>kUM`%U3+msa>ADQ`n(B58fA^%f zeS1%O+k}2!i66}T;XUb@S;i>F*{;bqWRUd#Az8W1+Z>UZWC%)$#ItoYFcp?P2t8c zKK8o{n4W6^V>*4bYpFXs&SeuDq(X_kGgr&;!OeU{zxRbL)HhoAeXC#UIhtQj#oh#VG~iRF3$Lf+sm z;d^@Jmou+$<(DUS-?-7Z97*!eMDuhZ9OQCYdLTmxy3g?`%<-vx=lFf!_dS=+e9W$q zq}vP4Hx9EawW0cr!xs|C9t=o`YEpikE9@keWR(8lGMtH*ENAbL+y8m2_lI`cB)LA(nbVk--}YN+y~E~byV(Y^xzDF{59WvaH9t@?5rFOeB?ZP$g(VC z%-MeLW!V6(mUg@(R)VZwBxJoF4~TOR=VV#6VwoaDzFFBcWhGVKY?jztoe=JTsCmSW zcfbhEL~Qv<;K%JG1CLHQtt04308aNL0Dmx}38jIfq?^l1$A^yN29Ap-0U)7RViGYX zlz8FDGOWB43;?HD)YOOF#16j&S;g^RPd=2M^YKp>SPty(W87zu$3V8!rU!Rhm&?IkpuiB0kirCBlXa z0mp80rBQpLiR*u!<#&~<3UkS|JC!FZ@ORuO@Szlo6n?30ePQmh?yZM-(pNKSQh1i` z4rSX8umz1xjyLE-*@CF{(NRRApwDVzhYg@hhc_3;1;CCY0MoIpL)L4fmm2g*kYxj# zgWt1)DQ&*|TdPxSaMjFDMgKz>RodW$nxO9eDCWs~KP8sn?|e5$C{}=Ug8uH|Du@ZQ zxBLg?1DM_HUeLw%0Ntx`{8T~ITnUaUfqd*yE*9~vF7b4I%_) zzZZeIM!gD(&AFvjbCr}qGNJiq=Fp;(Yz2{Hd$-XM^*w(j5Q|4xS;a&sG2+-GEt@9x4c4}QD9Nw z!sJ3EE^Iv|71FdpiYr|Xs6O>S@;Jy%pvMncu0@s~Q=pUwpw{Yg?T7(yG^LI{Qgwn| zA5X=`Rp=au?XFbL0h!m62Aka}f3L9o<2xe>xlAjKKMy>MDj=t->2 z^`s8|wl3EADS+JeYLPi-DN5M8ADUBdWWidmXUbW4XzHMjyonpsc}FcBAScxh>c1{x zZK^g^Z_tMlYb9G_IT#xyLsnCxa{84LS7`vy4=71RlaLQB-qh@7`COsnX}7Bv`>*fh z=)4%uy%Wa1^`LI9>0+TTd)@dnjM~+Zzs;iLLCN{~j|k)b50@MF;R{+Y?myMqvgu-P z3{z4kZjaxt@`g7iz~B@7kDliCd{1-xi~8KYKb2+Lj9q$=YuDOlc;W-ka$+xt2QFk> zPzoNny2HGLU3ZgV^J+lm_~igMwPvhXUFzj6JoLG%*@86Qu7|6>l{b$GhVzqrsg>;0 zFq-TFD`yW0b`sEi|-?vT@~bdQcmn$zjiZJgfPh*updG z`yh1%I%U6!|Fb-l*uYm$m9Fn|WfNaJ)$@Xm8+%r}+M!lgwmWUBQ3rERX(>I4fGa)i zT9$PYpqaMs!3BDnHWL*bTro$(L3cW(on}ZQzxy#82O2@EM?#k5b`2RExha}%9LibP zWuA`JYNL3d?VTTuVV+`eXp=N$Cq}RGw8=HH%e;JgU$*8)#NRz!HM|oc`s)Llb4Lvs z@9|XbD$V=XSHx{Q9+gmC2YHAS*a<5<#Fh**a!w%Nsj%@;8x)$^8w>MGYhBUcwGvno z24nbbCEJYL2_DZEpI%?PCT_{)2}$kSIk&t1DvzhDWXB2qH+BbPfc^141K}eJTEU0Y zk==pqw3=(WW)991)03FE+LM_0N4l7hfsN%pU_F}2#0rK50j+~+p%a>z6=o8c3XIz& zQprGrP4#7W>3{=e30&fkHzf1KppYV>i*Z))EeE@R+_cSucSp%X^QsZeq?<_i9Ppzjrzss$s_|Di2w?(b%|8Atc8?zk($jtkow5z7$iM zJ+)^!RdT>He<&TEm0z6u{f8^RcC3zT?QGU=I6S`O71Hc8QP-^yp>ku zFdzHV9j42RQ(A6MB4eQ^k?~eWWQfxYrMgV}rsdJ$Fde0EqD-=A;4qh;Q^ON+i{T+6 zPP?#nn$yb*!^*}X-aaA21}w%_;v#+-nLdKeP1klUPeZ|Ho;t?X+TK-)XjTlz^4&_y zifq@?nVOR;8q%(!MT5z9Nf)^?R;yh+==u&Odp@AcfMh)s@{dS$!!9#e4S;Xy2u)F@4zxSC3RVC9VY{dpBR^BkFwjw=QrE1>Z`i!1*qGf}nI9 zIl=+(4FK|sIT7#0UeMy|#`opajmZkn9pT}=ryVC6={Vu##zcMGlzE+)t=1kjieg2Y)G3Wk!#25Z)%vPuAGs8l+lv_`gl(Q=wIssC^ZQv5rp8{a9WO&3ftVo zTWC9syDKv*-m4@*1p!MDyjm`zW^>Pcg+_{NE%IiKn9__lY=*%ui#9u+83!JP#Zo)1 zOcT5Bvm}^cS;<*P4wH~Bi1f~*C(8c0*S_OIr?_D&Zj^E~s=xJa?IOaa#z!X`^pR7H zpfJ_Pg$oQuCPz?q=0Xxq(vZ%Pba$0A{-{%6Sw`b+R>U>m{qX=HmL2YYc(^88-pKbv zjAf#}KBm}R5&S;zR>r>(u7mi_NHQ*^-pENQ@;RyZAZ@R<@r4hy|NT(n62K~hm5ns_*JMIsZT8So{4(IdZ%eXeG|65;AK{uj5oT+3K{LzU6vpE$@?M(maHOQiPqZ zvK_phVSBD--FZZo(lRsAd^@`bAPtLg_|NLg^25$6~q(dM~D%Rp!YvrePk@zzlqE&s=(CMc(b270$ut zD=xfZ%sAM@j*X3&ue!KL#;l}+Cqm+my#;T%p!p`V6VqV{e}Q(`YzGuZR7=5A9du!} z<-01xC|r?;O*b)H?hcD_F^x8eqVukr*ZP~%yq6omLuZ@nk#hVxf!FG zcP-De9@JyNea5mlL+l~C<&&$gFJ8I1^!f&(JZ)^u-CUerSW<_R1DtRxb7v;6-dYii z%T)Dg`c!@m^hvrHkAN{x@HAr1|fc_c8w=uw>!<^4WC7 zQB=ww+Ipi}+tY%x*wcdZZ*?tLhS1t^lfCZi4viJ7)sR2Z%gNfTG$Up?6*s9ML`MWq zCr><=EO*+ncvp!n0ZNWBWmZ?s7m@k94IBtp7}vT-QRiZ;DC1?d>WAnY4qrH57^~IC zGj_mxK9>}G=&}*4iCR7e(-(76GV|j$-Fu(b`=X>XLJ!FGt>b2347xVlgLTu&Vi zxuu5g7f&8)oabFDimV6q1nR?v3{HEB*SpOkhoq(+LUvH)$zZH$3K$Jo8L~6Y=?;r1 zSzuubE5jybo=D9Hp-sVMJkT@+WFT7a^xWdYQb`3+?$ODa3eKqlGR9bzD*2x16Y|Nk z3O~uO;IWx47Ln2MkR_0+JaPjn&m77az z^GkCw0`q+#L4-m1_(+y&8H)DED815f2GLg6mv7vhp4(WYIK63ol7ndq2rN9$t462x zJg-WlfsuLU4&>-%WK`em&`?G6p`jN`eSVG@=n1vjp5fsxIw9R7P|g7TA_1?vD%gYH zLOmlNz}tZ2%&y9x-X~P+wX#+D!^)-Aiet-nZ&wwcs%^{FcY-Mg;T~03-#?hH?~=eq zeL{PTNM}_~i~CYfi~A2B(_**k0>As>&YEV-l1`W|>aTJ~Wx0IQL4Ohn*CpbJpSUch z4W_8WbbSO6qm#jOxre0QX5AwNX$M_Jj^~c;R8Pp=TKW5h3T*%P3q{z<%Nn@0yb5`p z=4SICpS$JB>5zK{lJ;gwobHE!OX&U3qykk{k{7%hy=7wc@~Db3S}})|_`EC!OrXMl zs%(;(mnrJMhFq70m-iK&S|MHb^;{?;1}~3_mp-Jz*4w=0G!&G!$=cM!J5$<(=;Eil zQnH~oZFudYxZ?iv&DFK5EAy)xb2FtQOXYVRItrr8(2=a#PcU%?-LuXrB^-(1G@P(Z zzQv!f-bWLCPHLk23WP3}fsegIag|+uf8vn0*{qoa59*2z_l<)Zrv;l34>+CRl;A()w2zh^z|-{Rxd{(P$5bK8JodltN znq%&`7TH3@`^Z?Nn^CYEv()^_+ue09txYA*^*gt@6Hk>-{|YahUt+1t<@%}!mNC^u zg)oK|51wd&>mjlO!O?)a%tsiPIZ`?u*uh<7_*ku8Q#Tg)IO32ccGPb6$-)MCxI`>< z!f2I5BGA?$@7Kq}T8;TxUR1lh;9#E5me5lb4BLBEXX0~UMVdxhS z$>k;;A7w*}H|3tyVTaF^R1r?!)!^Q}{J61{MVZMio&yj&S<}qsieUT&9%fMN$I1*~ zk8D!4?QaL4#2x*fUN%=Z?hC80idm%Ul=kTom-gDdP8zQD%NaBM@S!fIcdTa9y$#{@ z02b3hiaSpWq_-+bd`=jPb8#U(pv zwk}S;c_q5$)$Y6|-Y3h5Dzr^Qg*%IAUQgWWrkQB?ut)=+)|Q-lq5-F?`&lDnO?`^O z@^E&DuMHXy&WNM7Y$qv&o`^;~24#wUT)jIX5VQlQ<7o$@XLv!8j1E?1AIXlha2}>{TwkrG|q*rV3CWfHR@>rC_cI1YdOVcBKC{^^#>pGeb<!LmzIA>E02s!@eh<0k7IAcPGbX{(Gb|#Q}`nJemhJeOLG-dN(FYxmZA*yPw*aTk6S~Og?zZwOG^Cfzo%OY7+vWs1j%UhG^(&Q=weGXza7dNKz`M zC?I5Csw#^*MS20A`E~)8`SdQ6RN(hfu1mEN@aiC)hSO2xP?uTMl}mi-N?ULb8-uK7 zRNlcUjO^dc>uH5255;io`r_e1dXVg%ZjW^J##XiM6I&3Csv^g;V^SA7oS2fsok{FO z^t}j~Affiw8vIim+A6P3dG!XbqHB)|3UrmCkza=NOvy65g+!adybe()ozpRj2-F&co9RGdSyMogj{u$V;nmy)KmgaWwIEQ;iy5LAQGGRP<|Vq2vJxcX31L}~!VQZlDl z2uptf9*F?mWzqmrx-n1Zme`e-KX)jiX8gZo{$&@9?hV(LAK7x+R`M=5Xcp&JeO{`> za1TII$M_nfscfkkA$QBgz(#Q+u+6N)Dc!?=6*uF({QbuxAg!)O|? z;~0G>jkk@b(3*b37`zK!>|eU+|5^)o_+Dm$qQ>&SDEiDvN*O{%)HQ!TQ5Fo80TMVw7j5c zd1fZRSfCX7`tq|co-~XXPA-m`ci$d3`OGt~U~c$HD3(0H@ZGo1pR0{T zoslpIyb(X4FifQwj_!k@-V=sn`(POD3B&PyFpT9f3>b#d30sln@Oh7aX9fT9eb!hU zJ!u$&eGnit5%8v`2q6>yfI(x~KriASUR0P8zt3sEFKEA?(|#{#zgM*1uWG+PrTzYr z_8TucyeR7WuXpd>eM$WO$`R1BIQmV)_>5uvI(_~sO`6{@jJ{tpjJ|Ie#^6y*n4`)P zaB?PcoffOym|ns`)Ba^2M%jl|+5RS#tsh+Q915Px7aTpf-~|-CkS{oPaKYzL@VR`! z@q-I4px{Ej;KacNS5R;zU-06=1z$zMSMvog9bE8JDEO&-!O4RQehCG?lrK01E8o5Y zfI{zMxxo-r#gBTH52u#WqJ|iEswhURDmuV}RaqWZfK9j6w*0E=$Q1w+1OM>7qAjF- zeUBOSmv(M`!}}}l-}>tReQf>N-}~&|U;Kw38UNVN{x4s6`d|I||MHUm`fUFnKKaK_ z{LYX6m7~8i{-6HbnV-G$*1!8_f9-F7`<=i1^AjKb{=fBV{ni~+$wNR@wszNqG`@tD zN37$|irYQ2c9E)JsrFy+47&cj(ya4vml3W?rkl@mh86HM3$)j*gFyslQ2g;uM(A zPhVZeqh^R1;JhG4+ZboyyIzUn@6>3HzaM*t^mk|fDXsNc{?|ro=gawjtib;n#s5nq zV`WphY=lnFE-wfUk8%zl0vg4`x}4N4eUtBUm0L#~L;KSH_=L#ELLGS6#WeXqu8SBQ=wcr28&R;(tH%X!yWlyqUn@hSv29 zI=eKizt}Kp*8UBfbK`9?>GAbWYuNo3&NQqHeX(JpDlGR=5W_km6_?KmO#t7YGZsgW z8^(_xHy$$Mq7u$;6VSdXB8Rk zIB{h%tT$3M(3trgICmECY4X-r5X&)c_*O3p$PjL5u8mWF;)NH(N6GA*AxKTh(|k z_Jf259sXh4DZkGdi=+Rs&oKT|pJDumKI1%Ps&XN-y`bg#q5vUvSmLv!60-y^M8#+n z{$c+rzwrZZ;VTPW6a?jR6ARC$d3j@VPX-b@+gQGWjgF@TKWc$ry8q# z3_mSj7E{R)^Q=7ut?H&^35>ByICu|Ko38J;zG5g$d3rW?p_YZgQ$5#XR;-439y6z2 zk@I-2EYIGES=#4op48!j zMdnq*82AUL4cJO3^ZzuA!N;zP#Fs_lcZlzwgD?vOx+lf=)39nigB%kd=kf8Z$on?& zeL;NR7T@0upzjiYJP%QQ%rM>(fBy+&evO-Z=->aN{r)+a9{cg}zvJVF@bP~b#`)t( zJKT)_9RA$HhfifbL**UAc=+?5|NKYr$BzPb$8v)Ba{&7+KK?JH(fjG2fls+Q`u>y1 z`~)&vu&IA1{%qpIQfVvr^9J0E-CO<$-iEByMsZ9q(uN^4akm>p*fqetgpZHmTP4Jf6D0N9 zLQ-%hb3xA2u_nk=EC<49UY?Xt-E^=Vkmj!@cBqOH1n#o!^8I2`8WWIopDD0%n z(C|kcPbCA7-HvR}PpYn;UFYm}R7k^nmUy>PqJ?yqX_W{$YB}IF(({*bl5dg6DlvIz zsM!u#*s|g<3V=`IhsbC}R*2VoNz&2XUzrPOl+A4hw^Ni5*4b=3?6g^17BA*+G0RJ~ zy63wHwxmcdmcP|uoizVZy?*Mx908fuaRA3sL!zX3w*C@;ECCRg*(PCpAhuW-BpjJ+ zD>_nU&{FHFj?}Yq-J@s4(GGGYLX0elP}i0~v`j~A3+5n9u)|cR>IHXOuF_gi7q!2# z>qe~Au_8qw1iRa6hhY@l-mA8l&mv1r2`Z;D34^2&+(@(9n`&4?Lv}+PA*iJdQaZQxR#c(^TBgoS z%rS2?3B@`r(ZS~DF-O$~mU_&o=Bc3KEQy(KM|+_fcxZjwvO`Vj01a)+PMD_@E?F6x z-)8X^xqHY&pzy6EY=>&L5en*|0tzUeK1-^Wn8SA z#j?E$^OML;C7xu@&TY@~t2+q`RgDsBVe(>2g;PfOqe$L>XTeS=1AeP?bbA<5AOi`? zlftTHseKHn2*a?7nIUfDOK6ORFbo6S(vL976l#n!6yjl1Bs_=6Q*@EQEi7_T#e$Luo_zF>H=*$ny5xW2a=)6M`ktFS7$6R8b}a_n^h}Hw}FtQ z`TUH4!!ddRz>gElPsK|ajL+QGRx{Pj%PNX2zomvoj?zxE6_SP{`S?_p5Ybrd?>fFF zN=6REY~Gs zqE!+c1xRk^ut#o~;dO3YPfB^Yq2QdUrcAwRi96G%!lTj5UVDWN2KfwDY@)25Fo z!8OXyO#FO7KH^h$i}9fl^ZcNr1fMRtsAheP<}))}kbEXJSF%Hl4OMS;lLE0Xyt!#s+ z4IY(B?M1`mc&kEhp(iY}f)c*K-j3bP%+!nH!YT!AG1*KPGc*@}7nD}8E{UwoO)uCL zMj6QokfO2@2;oFE1M`sbT)V<`^CXCJ<)1Bup_M+VB&;1GkfFi|!%PulWbJk>A!*2v z5GN6{+6pVCY7uKjtyLUw?TWaFBsqY=lSH+PQ^FvJzwz%C?fVsDar8g*;W@p3-$$qJ za6#)EFbwhz926#-KRRlVC*mNqm4WYinyiuMAvlF^A}s&#zTz%vRCC97Z7*kn00lgq zyB`ZesJ}a53@aJ^Be=L(=xz)ljK`{G&4ul4N2&CHAQw0%P$L1O2Rfby?=;VCsks5( z$&B0_(aXes5U8nw$+Me;8Ua{7Bo^CN>m9T=m8_%<(I;q;t)(>2c6T+TR6pN5TDHw% z1q{}R4BN7|6brQiS@Wxw;kc1z-=U1%-73w=s+CfXnUiK@u@TEup^R*x2JenmY)j`3 zL<^<1h1)Csy&#&7Z$z}im^=OzW6(JE732KlRkCGOZ7Yo1mQNE1F;*oe227H7klvD? zRn!wFnym_56T{IX&KyIafo_mg+qaUW+Khs2O~OGP4?^ZcqVQdXtO}f$Il2W6dk}>! z?lk!<)Q>%&YL-J(BWA0EB9PTgqRqGxcbdY%Sym3g+e)`C=mx?VIL%H>eIy~tDuBlE zte7bUOXf5av7J}gu|T3sGpU9wa>Fg%S^*Y|Ov~9}QG%$@n zpzpDcQkk(>QhH16iP0%4){ThvE8B(!q`q0BkeIRXb4hqDm|XR`gQD;=tQsQPpyEYX@nQGHWx4=sB;HD)a|z z45U*j(-iuHQXP_EDjfq2>0-a0Z9It3GTWA|+77;GS(y{jTwZ2%L=T}{yA!*1X3LCb zr8&2PxI+HtvTLPbffq!!6Wd{>Z7GN>>W+3|n$2l<&563^pnZ}OY_3v5kyBwUvPmVD z5`!Ns0=d3`inP;XNTM#tbTH^9Ik2{6S144Kq$|rIqAT#(XyB_Q=>tV9Wb(=4k=@5R z9dB7-s;Oq_K+jg(IPl05uAB~n@tB1bLqcS0;8z7?o*Z+$_9W`~+cHazRXKJ%*G?(R zww`Jw#3@9!-$Z5wBdKH%-3qu6cU6x{!jO|QaYLw~caWvwlFby!G)ZJz-Et?V|knT_sG*t&Bvg!k~_tP#iI$A;ZaCF57!zY6p zVUT6}&{vsE%~n{*(+I+9izc)?UgA~|2Pxc&wBvMi0(P=lBP|vL&NdAdiTu>q$96(R zo!F{NJ0O|P^rJXXs2m}3#|Wq^-it>oPBT3XAq{son}!)gX<=At20;?zGJgdZWF(Uc z{0((m3id{dh1fm^g@q7ZK%NKO#{un0bsi8ZE)T_O&STtZR$fU7*ovDAe7(ZrhJSxu z`~K_3;^Vqq|{XSKZ+N}-83GNmh~f>@db zNYp%(Fcgp^u5wi04Ac%E4AHVA5_G7%Y$VelV}#C*p&ql$R)}vz{lH-t=)#dfYZ3mz zhyX#4e~>QnH}J{d7%W)3@DGAj{>Hb2f%#Sb#^zoA9@5~k;gIQ7?RQQ4J*oZ16%h%K zYbx^hW$pL0_WP>#`)P)d+V3Up_m615KW!MsGotOE)zaY@CvpC$_WQ@Q z-#?-K{=CMAzoY&Bg7*81+V7v#e*Y9)_5}@J*3#kIBGZ3HOaF@Y`>WdTzpwrNnqiQ2 z9shn_YvV6yE>pO-CfoQ+hC%&`f4{8N`zwY)*MjixS2g_bp}{!7zhBefzhM|OCh+gq zHTZ98@c&qY{|(`HgMYuN!T**9|Jxe;?`ZJ9tHI-HgQVy8H2B}w;QxsR|7t(RIXOP! z0@d6678P!$(H(~;^enh2^2=X+GW{5eoKZJ7k7v@)BK-`mdL7SH@fdv4aDSti^(3+y zGD~73!kz-QvnZl!ryGm7L=`TD3_eEbnc9a?g~?w%O^Z+!FQCW|WvZa` zD$;)#=`YACC>_!92R~g*pF}$RP*YL~{zaq@BYiT12R8%<>&5iTNdHn1&ot7%jP%PH zJXewa4~ps6kp7Fs^aZ5EcZ{1Vb9k$xis|077Z3H}*I;b3gS)siNPY@g ze@SHhB=Kh~Q})XM`2EtdKaH$^BC@_rWk)k*e+B?21VEPBuOMqcWc^I0)K`)9{h}e+ zQhy&=e_3RG6``F~L%s$+Z-URChUNB1eMAldnzuiXY`p3+_%%KV;I)dvl=}Xtkv?7s|%9}p0~#H)W!ul`p6@Pj(Qan}z! zNro-I3ZTC#fifg~y-31nmV{r^N%%S^VMr(88#)OD&@T)l86tjNC*tcFBEDH9Vk}F< zKh}x(CMN=sXjM1-hE4\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220090557-Binary.backup b/MikroNUC/20260220/20260220090557-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..9314b52f29d5ba6f84abbb74cfb4be34a97be446 GIT binary patch literal 300264 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220103113-Binary.backup b/MikroNUC/20260220/20260220103113-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..81e908a0d2233d13e05300d4185661e4bf3e5eb3 GIT binary patch literal 300264 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 KWML!Av;P\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220134006-Binary.backup b/MikroNUC/20260220/20260220134006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..38bd35ce92115d7089d72ba5e433368e210f4dbb GIT binary patch literal 299469 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220140006-Binary.backup b/MikroNUC/20260220/20260220140006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..c1caaee340f66bbe9a4dab5027ae2d83a962c974 GIT binary patch literal 299463 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220192007-Binary.backup b/MikroNUC/20260220/20260220192007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..968bd1498ee9a893cf3b039fae6612abae8c0c47 GIT binary patch literal 300426 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add name=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add name=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n/container/mounts/add name=carkeeper_configs src=sata1/carkeeper/configs\ + \_dst=/configs;\r\ + \n/container/mounts/add name=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add name=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add name=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add name=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add name=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220212007-Binary.backup b/MikroNUC/20260220/20260220212007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..07db11c88d6d4a85b779399d5f7ffafe04a8a853 GIT binary patch literal 300524 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 IiSow(4{$F`_5c6? literal 0 HcmV?d00001 diff --git a/MikroNUC/20260220/20260220212007-Config.rsc b/MikroNUC/20260220/20260220212007-Config.rsc new file mode 100644 index 0000000..a0b9824 --- /dev/null +++ b/MikroNUC/20260220/20260220212007-Config.rsc @@ -0,0 +1,2720 @@ +# 2026-02-20 21:20:06 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=10.10.10.10/24 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=10.10.10.1 gateway6="" name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors=\ + https://reg.vados.ru:5000/:https://reg.vados.ru/ router-ip=10.30.30.81 +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://registry-1.docker.io tmpdir=\ + /sata1/tmp username=amsternl +/container envs +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add name=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add name=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n/container/mounts/add name=carkeeper_configs src=sata1/carkeeper/configs\ + \_dst=/configs;\r\ + \n/container/mounts/add name=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add name=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add name=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add name=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add name=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220214006-Binary.backup b/MikroNUC/20260220/20260220214006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..cdba8c713399d1a0f61a7111964808db075c6262 GIT binary patch literal 301270 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 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260220/20260220214006-Config.rsc b/MikroNUC/20260220/20260220214006-Config.rsc new file mode 100644 index 0000000..87d263f --- /dev/null +++ b/MikroNUC/20260220/20260220214006-Config.rsc @@ -0,0 +1,2730 @@ +# 2026-02-20 21:40:05 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=10.10.10.10/24 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=10.10.10.1 gateway6="" name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors=\ + https://reg.vados.ru:5000/:https://reg.vados.ru/ router-ip=10.30.30.81 +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://registry-1.docker.io tmpdir=\ + /sata1/tmp username=amsternl +/container envs +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260220/20260220220007-Binary.backup b/MikroNUC/20260220/20260220220007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d97e020f74dd9e3d9108735acf42ab2d5ea8635c GIT binary patch literal 302374 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 Q$}CxFHcI3lC(E<{7rEpGg#Z8m literal 0 HcmV?d00001 diff --git a/MikroNUC/20260220/20260220220007-Config.rsc b/MikroNUC/20260220/20260220220007-Config.rsc new file mode 100644 index 0000000..37c39b1 --- /dev/null +++ b/MikroNUC/20260220/20260220220007-Config.rsc @@ -0,0 +1,2742 @@ +# 2026-02-20 22:00:06 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=10.10.10.1 gateway6="" name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://registry-1.docker.io tmpdir=\ + /ramstorage username=amsternl +/container envs +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260221/20260221232006-Binary.backup b/MikroNUC/20260221/20260221232006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..34830607b04ca28161f02d62d561f119c457d1e3 GIT binary patch literal 302376 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 ZNwu}>HB%cQq0Ew%W}`$Na\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260222/20260222002006-Binary.backup b/MikroNUC/20260222/20260222002006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..cd39b25ccd9720ca85c112ec1812b23bef32569e GIT binary patch literal 302656 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 KBF{ltp8daxE>N-n literal 0 HcmV?d00001 diff --git a/MikroNUC/20260222/20260222002006-Config.rsc b/MikroNUC/20260222/20260222002006-Config.rsc new file mode 100644 index 0000000..87cd066 --- /dev/null +++ b/MikroNUC/20260222/20260222002006-Config.rsc @@ -0,0 +1,2746 @@ +# 2026-02-22 00:20:05 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=10.10.10.1 gateway6="" name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru/v2/ tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260222/20260222004007-Binary.backup b/MikroNUC/20260222/20260222004007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..8a9b21f4433d66a6617bdbbbe6ec4d94a16034c1 GIT binary patch literal 303255 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 B=wbi> literal 0 HcmV?d00001 diff --git a/MikroNUC/20260222/20260222004007-Config.rsc b/MikroNUC/20260222/20260222004007-Config.rsc new file mode 100644 index 0000000..5d3aad0 --- /dev/null +++ b/MikroNUC/20260222/20260222004007-Config.rsc @@ -0,0 +1,2753 @@ +# 2026-02-22 00:40:05 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=10.10.10.1 gateway6="" name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container +# download/extract error: check registry failed: SSL: ssl: crl not found for: "CN=reg.vados.ru" (6) +add cmd="sleep infinity" envlists=carkeeperbot_envs hostname=cron interface=\ + veth1 layer-dir=/sata1 mountlists="carkeeper_configs,carkeeper_configs/.pr\ + ofile,carkeeper_configs/php.ini,carkeeper_configs/sshd_config,carkeeper_ap\ + p,carkeeper_scripts,carkeeper_tmp,carkeeper_sync" name=carkeeperCron \ + remote-image=carkeeper:latest root-dir=/sata1/carkeeper workdir=/app +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru/v2/ tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260222/20260222010006-Binary.backup b/MikroNUC/20260222/20260222010006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ede21201b3c087c333e7e250f0ff5b87716bd8e6 GIT binary patch literal 303527 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%0AhCdEP*38qWaEWFgd6=JPF0p>kEPlP#)mLd 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 ImF3z03((h5Bme*a literal 0 HcmV?d00001 diff --git a/MikroNUC/20260222/20260222010006-Config.rsc b/MikroNUC/20260222/20260222010006-Config.rsc new file mode 100644 index 0000000..717b23a --- /dev/null +++ b/MikroNUC/20260222/20260222010006-Config.rsc @@ -0,0 +1,2757 @@ +# 2026-02-22 01:00:05 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=10.10.10.1 gateway6="" name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260222/20260222012007-Binary.backup b/MikroNUC/20260222/20260222012007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a0691642047e8351dcb696c70c75cde19176d148 GIT binary patch literal 305075 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 K?pKKN#{UbaulOMV literal 0 HcmV?d00001 diff --git a/MikroNUC/20260222/20260222012007-Config.rsc b/MikroNUC/20260222/20260222012007-Config.rsc new file mode 100644 index 0000000..e4bed88 --- /dev/null +++ b/MikroNUC/20260222/20260222012007-Config.rsc @@ -0,0 +1,2754 @@ +# 2026-02-22 01:20:05 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container +# exited with signal 9 (Killed) +add check-certificate=no cmd="sleep infinity" envlists=carkeeperbot_envs \ + hostname=cron interface=veth1 layer-dir=/sata1 logging=yes mountlists="car\ + keeper_configs,carkeeper_configs/.profile,carkeeper_configs/php.ini,carkee\ + per_app,carkeeper_scripts,carkeeper_configs/sshd_config,carkeeper_tmp,cark\ + eeper_sync" name=carkeeperCron remote-image=carkeeper:latest root-dir=\ + /sata1/carkeeper start-on-boot=yes +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260222/20260222014006-Binary.backup b/MikroNUC/20260222/20260222014006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..81195979c8d4f92ecca88a292ce7b514d0460ee8 GIT binary patch literal 302761 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 G_WuH!9CcFw literal 0 HcmV?d00001 diff --git a/MikroNUC/20260222/20260222014006-Config.rsc b/MikroNUC/20260222/20260222014006-Config.rsc new file mode 100644 index 0000000..3dd964d --- /dev/null +++ b/MikroNUC/20260222/20260222014006-Config.rsc @@ -0,0 +1,2746 @@ +# 2026-02-22 01:40:05 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224122252-Binary.backup b/MikroNUC/20260224/20260224122252-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..7df509c7908b5b99c64804aa070c00fd9bff0de9 GIT binary patch literal 302763 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n/container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeepe\ + r/configs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224122441-Binary.backup b/MikroNUC/20260224/20260224122441-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..0ba3e2f7046cdaa821b3271a464f63fb001d7c6c GIT binary patch literal 302761 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 IvON2L0d+=ns{jB1 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224122441-Config.rsc b/MikroNUC/20260224/20260224122441-Config.rsc new file mode 100644 index 0000000..715624e --- /dev/null +++ b/MikroNUC/20260224/20260224122441-Config.rsc @@ -0,0 +1,2746 @@ +# 2026-02-24 12:24:40 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224122638-Binary.backup b/MikroNUC/20260224/20260224122638-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a9dac07a8cfa02b50ad2dc8b913852057460a5ef GIT binary patch literal 302763 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 |* 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

    ~lk1c7%NqkBB?ee1uPE>66W@ zcIxWb`yYqKyl(!cg`e@X>_K*mUVU6;CC;kHHp-Q(AK_bQn{{(cA}u8Vq1zj&~I%(7KBo7%NV8gAA7^G3hM`RNOlRjYUfUoLE&HKA#% zoU;8}XNd3Qa!&yr4|nTJw6C||!ZxoxW7$ip<^9gW!%^MS_f1;aXY10#x5pK<+)Lj> zY3pcqyw`!}$Cp}^Ylzplx2e#^ytr3y_2qGlseNBfN*5mmaki&yO&CA20KnI``5Qt55N=BdgES7cYHi=+a!wpcrrVJf8ccWY2)D zT?__g-i)-qaV9zU-TBk$!>{I<+?yukcIZ)N6v522^&LF9x%2kC&LPL+4$Ym4ZCjqT zc*%4dMXPM9XDe`-qsRG0?2D&wFL-%*+G2P6j?FjtyB%ra`rv7}+0tQsmUM}GHs9*? zyRy`$K6iu=rkQ=K=aaaLyH+(n9e-ul^s=tww@Y@&&o6sO6D_SCWW&a%88>)RiTSnM z$e;Wy>X2{AyU8U6cWj86lV8pKxNdgZ_%UqR0I%4k>=?gD*Q7j^vAtEGTe!^5(z z%evzcE#|!$oi^c(o9gCd*82PMP<0E@MfIWkp{7`lml~)UCruRDQhS&@o}(@g48p%d6@S=)nkPKI_(^WXF#1^X-o;Y_YXt z#_$=>#qmOxdqj>pMr5hkzUcm7#z^*-Ztc%9lSV$t9`8PU$F*mN3QwqAa-81myFRpY z;`X>U3VG{AYyGxnUz=LsuxXY@9KY8+ACrLB)Uo?c&gj3V@!%Z^x2}I~Gic`WqOGEO z?VInsl-3r@+vYySsc)FosVF z*1(lchk7>}75HjiL$`H3te=+7HE60iu=u)drDwBtYfRHEIz*S5H)J^v8WI=v?7ehj z)60=jv)cu3GTnhYbBykHA7||`Pd%$qamsbqn6iZYf@v3|1ro)zJjdA9BhJJXKKnr1 z-E?(!#>_iICKUAEcaOF5Mf*zG+O?tbqAKwO4&*+yX`R;dPlFW`%ZFF* zcQ%#`F6%`dbFcxi`_3*?s{gKJ@Ak8&Srq0SD_C~_*4hoe2b`4tvn{hudmT9(+vC!p zJG+Nvfp^C9v1Y3VoV7JPmhm}XZTG^vA7%N_&i+16-diWGD#q^{&fmgt+;}R0Qg7+Q z!*o6o>YKW1*mL>LASLZ+E3@eRF9Y75^jTcd zvTR^s)v>PXp%Ffbb9QZ-5V!F3gWcW(L#!(YQ119;qesXZdAIP*I(L80T0_kuhci3* z)4ILU1}h@)uy6NsX~nf-6Mk{io_*;4_8_b4%g>`EH-@#Gc=p>LQLM}5emC1>@S@;h z+o0W>CmF9i+|(^=xWy=kZezOQ(G%*6)8|u+f~C*kV(b{Ex_M=}1^<>p@X+sQK7aq%xbPLBDfKqL3|WTA}Kf=r=4~suEd(5ef4Z*9ItlxcsqdwAc+ryRv z9;feap7B9(I#1kRJN zgi?-#P;dl11y6wUdFZ)*oXe81aUP#9mGWhLg0{l9#Ib?97PFURE=)0pCe)(JP-S*TP+NZFAY2%D~|XMKmIMN1qc1xcc`X6Q1quOh1X67D{_nv z2BnWyJakH%cwkQPbHfjYgVRPoo*})z&(}WwLCNHEcSqZ|pk`deni_uMo?YXik)1R2 z5|p3VxV&WgXB&C*aF3fk?s4Mwbj~4$%1y#U+FL%|oO6Vh-=b?;7U$vko4sC3tjZ<3 zX6^aXt!iKRH0r}+WA-cl0@R*Orym_z~>pWgI zadBCZ%Nc_<*Gr}!-O+L~#gOtebS`j1EGUa)8$JtH1E^YLC70@=mzp~^uQLw;}JH$S)jt1E@D!A9HhbtCNJT*o=3x4ztP zcILLW?t*3=Qub|I_37i6hkhRy7jK}g{Q< z$p_W*x;|RlYPC&o=~kx+FV&wCklRfHC0{H$8SZO3XXl-NNK-sMp)7$&ceN z4QTBkdS(#TYijuT}e(M~AyKAoOfWrGK&eMnC^3Q^&bI zN_Y$C2c{3Z*ow=TSM;$keMHQ{n5!#8}+E_R%sbD)RA?rp+MgBx)Kzpx!Wk5lr+LIuv{lfR-P;qh4LH=+qKN5YZgY?eeWlM5s~IhP}s3#4+c zm@SjZgoKzS6XOJz&E`lsr1!1Ml>M>y`@{$j}2pT%WY16vkcM+4B1In5#`oi=ZUUjvx7O?3{wh*PlJpSRb#vQE1m=a$&=(ktLD8;(1$3why^D zX@+LOy1-+qs|lOmM-^B8k34VDt-h&8k3L!FxLNr4OcQ=;>l3@)yqWsWu<@g-YaYEG zHY7iA^7`cimpSh1|0JOFSrhLC%I7_X4jt7cbLOGSWp6R@+OI!KTzz0^?tVEuwCcwF_`7@Z%4SUoxN|?|PV1#HK}QRu z3ZK^NdO5_ON+A-RCLXun_hzo2@XeM>r$c9_j+nNPjo1+7~M_dmFQ zXXNYnw#%D6_bmE+`1b0GzL#>VUbRVEJE!9(ukvE@^&LMuVDy9M{jD;;RR;U7SDCM# zS3+>PGJzE5Nrgf#k1ywO1w59V!xi(mEH+1gi}@U!B^F3oJc(R}3*>T^n9G;&1ca0$ z=CcXy27XXV+gwwqyq2)&t}VT4{Bo|cy8m8MoH zl*w{?^qe*ToYEa7tg5cAzO2hHrK0;HqCWX1W@|Ea2AB`%E#sI101^No2>?<70KIiG z0|5E~KsI{YH~{1V`6h4l^Xf1P07e7A7y$H=Ul<1f=q=CV0iX~7CIG-h0PqF?UjXm} z)K3*gpjWh2S66d&SHAAr8vQ;(Ta>f|pd-55>#jcNJ-Oi+`O<#5lW0v zVyA1zUUzMvyE>p(cJkAzR^Af*(*h;7C=mkaXQ}2RK>uLY@ee2T z4<1U~>-g{G|J$=k&hoEJC7q-3Nj zHA;E9sZLtR_iq7^*WMr^8~~PK-~b}R4vDI59dd&7&JX}SpajNHg=CfiHYll&5>q5! zCMYoga57BGkR&Umq{!OcmI&!fG$z-B42+GvTgMGYGY}#Ql6@bPZ3LPzw1idQ+&Eyg9eOD zn2U}96aaA3<*5MBT$iT-8iMv?P^-LQtvup@z8yLM(r)tOj-mS^0t3iLmPY%ln^+B@ zhG8r&&P{dup$Mg>h%tJ!Toa;H$XU&QC`PR*#t^5ZYvk$<@=T{6O3`Xc(L~Cqm>&r; zs3~BWqD)SftA8wF__c_(ryq+LeJzq8R*Mtlo;8#p-eOS2pw|?!l&Mn0%2Z~$T&$KR zGSlT6t2$>2*)+sA4;@EQOM$w)io7o(&bi|-* z3lI?|0QnR!Zqj6`ag!!TNU}_kHju3vqgTWu$w%$cpGWS>Qg?qS z00==uAVsq(1couCkQ6lvwGim})z#IsLZBCu%2CC@j0=H*8K9xk3rXkjlZqwUii|9h zEvOb4Ko#l7$cmQa6lzT>Y7Xf;B3!CSz;%TC)FM1cmq+?DSeHk$lc&p%!~lFiL{NGI z!w9ng21d022Gp|vhPgRPEYLlYX;$bTXa)_k(wRgM%>tYZGQ~1gdXTO@{cC-PpEN@G zrV%dLh!NQcH(@Y{2zqbGr^3sMW?3TPS-o~Mj+btC4FA0S`6`^p`FRX?N zquzj_KFFa`P)GDX=m?RFXrz5ZBiaAAL)VKUIgyFtRH-5%SvQ%jYfUDz)?|{eya6C5 zvyJXPGKTs*5(|AE8AE*@8AE-Wj9T}tDCoX+1~76440K~PM#BU>D@jqP%}N>(#AGvT zYWD6GQ&W>pG6>b6pg|jPgP2?%5ARen(LOu6kgSFYVc%A=MBUMiv{rgbm& zm8FR_iBd&^-uCM~F|z%7FB?pHXc1APu*f(;E- zI2j9Z^hO!<13{$Td4uT3>XdJ*)4GQF5_MHZ&OoNpu(G^TlEh5i;!N*}8tRBd*M?fV ztzFX?lj@)YrMj_-#bT)OI{tOl<@Wd@NZ|+oGys5OBvnI1K>j0N^|TTmXQJ z0B{KaE(5?70JsVO*8rdl0LlU223m1q0245P+W>F}048Gqw*cTQ08GOGregpzFo2mD zz$^@4HU{7T0LKAf9tJQU16Y6oEW`kcFn~oEz+wzw2?nqfBM~+%$F%5q1qQGR16Yj# ztib@*VgSV$KnVu04g*+^0c^kkR$>5~Fo4Y%z!nT(D+aI)1K5rM?7#rd7y+C$0@#fK z?7;x`VgO}E0Q)h30~o+T4B)g8z+nvFoDskgObcR80KiEA5Cgzn0H8w^7(o@eIv3G^ z0R)l)HcB`s;i80xR=#`yhJgU(geYkPK(}xsm4=bi4wXVnZnV_)0bmfMruqUf>iYrE zTVVkH=w}N^u+jn54?uDkgz9xfNia$}p`O6DPw_L6V~d#r9+PkGAh?_!i(lxGS&#HyVxmFE!3J{&=Hd&V0V{ z;@Uj(5c3oB7W3J^=c+$guA-TK7rE+%daio$4>?zn@FLbCu5!79*u`NVVkcrOVliSi zVmo3$@Z)>aQ8649$sg{;>eL^m#p=acwxT`qA9BvBS+BlsJIxNltOthq&`LTOL`k92 zZB^_>DjW5q=UT)nRtOj}vx_rXIx6C1hyH3c_y_2Muto#QL*q3l+oE56sPR=^w6RG( zeX7y;0n!@Io@z{;S({g1`|9a4AN$z%yysM7>V0eTAOG4{Uv4P;N1P9(8Cq`G>t(sN z*u2V1E^QF>cj&hI`>)V!|zJQTIjE{e=&H_&uom3m^ROOVaPZ zHiON(yHRh{k1}8p=Gy;Q1`9LSugUjU8jZ$Zl<(7xM&p;{I}8WEDBrQ8(BFUmMYO{R zX`gDG{+G**#>}b4>Bjr_cIQqtPXEB-%Z>R{jnfCey&n&tD*@IIf3eXx{o8w|;6)M( z5TN|V>tT0qG*qkmQFf@_h@!pLsm8hUGx=d&M1z^Uo5jOIy{WQMqPXaC(t9-Qg+;Wa zo^Cf9=RUxXsR7jgH3u?ylIEZu8ZbUl4@Pr6Dn>)a$+OjJvL9z@LNvdfW{RQ60onCh z$d<`yE4jB<(quc{St5|V7dJ;qSAhPIyjYJ4?sGNS|BF??N!vECzfuo-z__~+9;%hy zsJo|brkP?Csdd61L9P~e`sr5KS36O0JIRYj!`_l=IzNESZ`J^FnXupIhJI-bY?x;C zJ3m6xO!mI%cLd|ShLPb0mauvkw9Yjq@`A3D?j zf#o%C>T7`Yr@mbe?+K^=Innw}fRYHvn+VtoLs(d})dBuneDHUfeFdi=Kw*723yJl9 zoE$%U8lnIui1&XTC~c+~47c-{ZaB;bVbU6g-Mw%p%3(X&%HrNmG)%K1hY*Hk;Af=| z7)5?czGH{}Gx8nQfuEM|ut-4C&r(PjZ@#;Xq@_%Mg!i% zQ)m~vWV8wE1I+WVK;RTS+J@%{J84)OFfJ1Qv?qjr>}B2)Vmo-|L)aLS_Y7k1Td^Nj zwxfVM{f&(V`>=lI4*{zN zL3}}j_|xwah^N_2$&2&}=2!uZA3X}jmw!c83{_;y#|MK+1H~yRd?l-^x(XSU@ z`p)xT`G&ulec!MB#{0Ja^;^F+`KgVSw|+bR8$bWQ|COJfxV4e~(A0nOKi&ShkN;QS zvH6{^eA}=5{WI5p?(vVkuYGm-h5xkZ{^y_n+28wxzy0^W?>!&-)R+Fs-}vW$?fiG& zc=CH+{+GY}KR@}V|MlW8|MX|?=0EgpubutK|N9Sr=>z=>A9?uW|Kjz(^P!i2{vUnx z`|mdwe)t>z_OGn{@&EfLf9t>8`N&K2fA^34AK&sbf8k@p-~HL2{6GKMcl_k~Kfe9{ z{JnpCbN$xuzP9w|f9(4CKi>bwfBH}V!QcGfe)Hm!oxku)|1f>+{mmbq+)4h~#Xt7l z|HI_Vf2sSA{=+}|xBmI%kKXyue)6TWIBjw_c&NVR$G-AUlCON=_kQo!KKM`H`_2E+ z)%W1V?n{@x`Pcu|5B{ZJ{@6eJ*So*?8#jLZPyguBSv`q)R6u<-E_lcceDL=>Sss#d z3D-B}#ehuw1`1FqJ4@M-t}VgPJn_NbUumq(e~e_`H;L#HadqlU?* z0XHPVp#z`!NTYG?ef=oRqZTVjFCzjb8Fg>GwsN279VF;od>hBn* z{tg44{tgeC{{AB`;5+%1X`#UagV|9pyOVIH(Kx;RRzH4kqwy_GGC$i7tp6WbxpVK) zjhlCtAFQ@+-)}AVdVrjeeQe_|xQ&0;d$o_3Kku}0tcM2j$rt~X1-rpMrFR1POK#)M z_x$R++W33?#((ggHvS#%gud5p{1fl}iT~Pd{hi|c>)ghtKkz$x$4sAN8vg)x-cg?R z5x3K&9g9}y5Uz(0{{AS(4gD|_BE%7Wki{8ovGrCPT=9*K1|oY-!%+B>J>WaeSJdpDuEaEOe zhPH>DEk5}BVRo5O^qAHkz=*Pm`=Lgo@k4N*oZ%{e@>HYoJ}@v`axXR-zYm)P0vcaz zG`@^=8ZMw08;y@jA3yw3qj6Qf|B06xjowOG^%?7Y=&M!6H%j~K7VH7?3szhe%cNDvY|o%je4vWzmRSv_`11t_KXyW zo($KsuKj&8?nfx@KY=6GKDiNRc%TAS=+h9-ck3 zxSeKE*xeQARGf4sAFI;VYCBGP>R>m@A_bV=4)hk4cC*-QevGC-ZZ1(ZOiLn zUzOXN*@+6hlce#RI?OMn!LKSeFwEklaE8}GYXAeylsX$*cIoVyiN}k>QBi5W1Ye$xvTn3VAX0IHJ?oZX zCWti!C=C)O5<|fYn)k`3rhv9;>f%#0X3*V^Ita5QPIgqVk+f<*8_9-%pgPpgde+@Y zK6mVgNDV#2$##n7H%$Mkqt2Tj=f@Nz@H-4NzN45A@|!;LiEJ2sozfgKMOh*cBriQ> zL^O4AF(c8Ol%EligL*oFfj!vNO@UW5Bk!=XDFo+~rV&I>qVA}Oq^nNw`0?T}%<@QW z1p3>Xil%-tct*esTn4OQYDqm+8^Pvgu%tE^$Pxf=QeUQT3x!62w(x;a%g-!QV5WkK z&7(E|EOFmY(fNeJ2SM(gNdlFoxUGVAmUlO1X9LjXVlP!zNNf|kS4&gT3E|-d@bJV8 z8dhPi$CK2gs%Vh7Xt7B1B2$K&hSnF+7&v0awumWB!)$4dr!iEP^>{}{qcoDK&2elFC06q}6+DWVQJC1A!AuiolhrJPeBgd& ziZt!dY)3_RSB-}KH0*T_qg;)$erK}DPKQVI_)*q}pqUBWWspPn_t}NL6K`2FwGkYIE4^Vx;LWJECGYeplJpvh3o^0Cc zR`cPyBrG9MZMU@VeBXPt68k<^iJfz`*xt|oDbix!{PjOYS}c@qxHbMh5U3FO$(gH81!tA4J6{!ywM0wRl@iK3?ociE7>*4K`Ir&9bIUV?jf~ zZ19wd3NE4?P!8kn9>X}DV!>rhRs-k`# zVYL$arIGXWHVGKCN_5I3T56Aq%sPdho;|ae5e`(-;DSbIHzz(JsK-rrQjaGp6-)(c zj@E5g20m{3?NR}dj89+B*q!3;=EryUy3jk#Ip%%BpZIhbCC;pfszjiRa?o5~yRTN# zQNO2>6zg!2gk;Tc*qWZiZ`n`NP=?Q~1Bt4SKyD|3b>YYGuh**3fVG>iCQzN9doJ|$WB``@5t;kRp9I6K#pmF;#C7vfKIW#iBNlP{BO z{B!@}KOor%BLrmQse0M?k=h0!D-XV5LKablu41$6Kg)&y*_j)E^Mh!R?nkP~M$uAf zK~`_V-|nr*tBF()-A&ZvIjF~r6VmpB2+Jh*APtlJmDkGy)_`)Xm;oFW`Qpq>mga4; z*|xKhXG7>k+xHHVC{qEw2ASBFZpK+&JQ%U0BQ{$$&x~MJ#_8>LjYZFSrMr>G6S@x) z3ZIS+Ul04EXuU`?=;5fSw_?kKN5kIAgF82QsQydO)WNkN3+!V8k_EK8W~hz|FeQO{ z>n)b@TWQ*-7 z;+?Krh4i1{ZWiWICom0AD8p8m$6bgV9!{Jl>L5~CghnVH$>~LfNl)w~aiO*jv4`A= zGP0bs)mpe0seF`0DtZ!ji~gZ1cH>;7N#wOL8ORueDHZ1`-%Ssaw#=?KB%qUrqARG! zuDuG!Gt)#yiz4cKR|8qD%X7rWone*^aXzhsW~UwC#YE&h=>*Z-h3)Nb*t@tjJ3D{z z^1|Hg?4@oPURVg{=I6rs`QDZ2>gCzl?F-vmSG(I+F3xYy&WD$0uY}>n-o;CoE*Ug? zmK2v$uy1jH>l#|&q5VuwDzkj5*132mVBF#3zeYp^n&iE^^LqW}!~3l*iVO;BUSHoE zuELMg3X@)IH0)`xXj6%H{Ea2eQwmAaskQ8B>wz}!sHVfEx(3I=oF-Zf;G@alS$S`S(87PudEKZ(#QUtA zS0{bPiJ0X9Yj?uwB?&{@gO;P8HRJ6KT|J{*6L?~p>YFhmfOH$L}c>K&G zECH)e;v8b#aPgSOwah(1lEbMX!ec_r(x%b++NzG2E2cEZUB-xgJNWFxxh(HO8+siF zuQ#$!ZX^@XO`@dezZk%A|I`#q8QM5C4P3zdHlDQnK>{64K z%%$cq?Z@52rDiWpidGhVaTI4!YZzsN7~v{OzSQi8q;ZE?5%rd^VQqEOQBo{5d8U?{ zak3xwEuO-)!TBkjo<#?B1cECx}YhdWVcvaPU2 zHcgcBcB(o`1BO9PO-(JqnT^S*LmHTrT-u#KU=o^qTM6;0$+jv93L51n@&DA+(nVl- z$+(wElLvkiZ_Gy36;^=jy&h_`1fAfATwjf{Y*czx~T( z{6N$Nj2|!88$Z5zOp`Ewyl{F#y;AFBHlJ58ZEul&F!uA7l%a64BHmLE(oqp*_ts^$ zbEQm~&y4}+b55C~KGfGqU{=~zvJ)4(qb&;O%%iO^FXAwnTbLOj_N|EbS~y7)Woa%E zc{!PWFrxLSP@(F@S=24k>`=jo-(4 z%z6fpgLp4)>uw1iJegSwlTp}TT<6mpH{yH`ASj%npaT}6da%6K!gIABhwA)HFV6Q! zLnsc1QHSD46#d^Cgil&|{H3TfKf9*#ep+<0aB$uj?R#;if-y1VPz2c!ieU@gDRO$o z+e(jfn!K|twN;U-1a^RUTa9vHIIXyzc^j&=At zZ80T;oed&Q0I1vGPCDoTVI63)H3*ZLL70R)QT9x=C-l;ihl8jk&JOlZ@HW7jZM7*| zLqG8E!w04vKUbciY3=;U|mE{OtUN`317K>bNT8WQvQZTfpWOC!IG{5M~3< zu5(ZfNj zOj!b}5}jNFz?Kv3%fXHa2q2 zb3O%Vl+D;qXEY!!`>f>w(N2bYf!mR_;X-DeumQVEcNJs7$|`w#G|YN^f#tWY?jdgvH7k~jN>{*3 zR<^aSx~PBCxk6eK^(>|HpwlibnNDYzxkvhrC`+wV;y6Y6eIT-f6_$RzF4+MP)}m`Pnm>$Ovl)vX%duiX?lL{K^alxx$AT<2(k-K zVDKgKEbSoSMG;hwu{k-j;aYt0*hXtO6IUV{qcgGr^Wkos3sY`~CKTE8j-H6D&Yt0@ z1=sj0AQ>}CxkobCj_ZqGa&yc5{tea^Od%GA0&Gd!?*TP8#P@ z#xbVe6;BcbvD5y#9EyTOaIAQkZKzv0h3c?ToaD#3$;rtk0Miv)*8<;F87AG`G|Pi2 zagpXl)FUq`!mG^Zm`2Fo8BD3SRX~gHb2rdYLD=sHQ|i0E%LCxC(sIxpwT#5I&cS%0 zor5%RXKvxvxTa>Ov}DBS#5Y7RzQAd%lru-a+E_CAgcq*kJxX^9R zp>8g*O<6U9=A1TQ{%c#rA1GvNYLIFhZ-tbd_mb6pB(n+p$=4oYovp$14(o@K!ogp1B{@!Tk`y9R)1NqFP?uaS?(DHS zrj#xME*meRk0fcO8AHz1`eHfnG&S@v>;f&Frp8YW3r!0`qC;OtL!KIk@~T}T=znZ) zEN69>F3nXNf>JoPAp`bvL!^f*Ajz1Y2PEB+L7W3qJ%M_uSuC9jX<*=b3IfejEIqv} z97}3Ll9X-3cO39^K|1G=ObAPm)RA{tHk!<|i5Br_D-uRgyimlGY zoirrd1mfA_olzE2Xc+>?wns@9KU`Upsy8X#xxCmsi`*d6urY}>qaKsw1|yL8XW1Co zkVDu0Qd3TEai{^_TabBXE#FZmK>>&B8s)|b8`hCgq?5E&(=^+bcwenlO7yQOpgF{u zmx~A^m9XWe9wLWXLBVd8_faMUi%)%O?bur>$iyP50LA&S$-=G&KC3Z-EX?NRVAx~T z2|~c;lIXSk-9m7XSh?X2lMPBTPHyHX&T|_Lo{irY zW)U}8S~GYKJrBEUPif;A+U@iE2z^Z=6(Qvpsn*lPbxC@lZl52hBF>^-yWOTA{V3dz zlbyDjn%YPn(kbABxZhV>2=$cs^{uF%9!&Eb$GJ+%x@hHhIh@34%}bF-+m z8-`ZiqFlvPc==?e!Z-MY?xMPpCWR`}QFoUS*^iUxoDI0Pa6O2^-k}jI2-(<}fp8(| ztfF2l@#Y#-#CpSE$gy|YZU`p_ZNLHiAk7QRXfN81lc=X+6MOE&%$H$d%p7C-^A}JQ zULS35$4?Z+80)u`Hf?=0$X`d0@u8Njwny&E4FRR7d0Rl1+WdARVCe!F-i>H$v?H4R zqOEfuN5A4KfprGaAk7ZhODdK=?cjgJeqQfLf_UQUy)BTd zx{(`n`-uw7%_DeeUsIIwttg4Iu>UZXa}35}A1v9!25!lfE|Vvwr%uO%!)PXP0v}sN z)Q@(uaA13WC{G@ydr@+`r-CaBS7)zWy0S2TVR3o+*23p{bGzHGKbT*;G`zLEbK}#O zzHfi`UUcERuU<|L)8TG|pvYC&@23Z7 zit3WZhdm{^%HzSPUxZ1Nj`IFtyNYv0RQ^zUC#}pu5fq&=68YK1x%mqhuFPMVz042h zX0Kendg;oQd2+^L8Jj@Wi}P16T)udD;R0c!zJD1;Fd6pyQ-riKRsp43>aE>$5WSUd zZ^zw;YS@O|AX~^2(v4+YBq|tOJs;?ffqj_n?DQ=y^x{0+>PIR+9Bifi9Fy*naqi&K z?J|EOE_Ts(X{HP z$xaLIoN0w4uW_<74Kj=R=@7x0b_5ib9Ld2t6>xpv86+V(LMc5exs|8Yu-rEXYfqyh zw|Xz>MyjQOPVph;4f5@ablcNf74J^6A}XHsE`ghu1RpDTJ_D=HmA~rbzh*& zPVtRsAEAS{lWu?1i*Dc7WUTqNG`)mfJ0b3>;~=2E5u7T=S#uTKkMg}RyGU}INa^Oo z`_hwoJpSZ|)TDyb%JSG}$6FlKcwWDoJ@OQ$_XQ4yA7rxG+WhfFXm2KP`}lNy7Td zL#M)2hI2G&k+I4*8cH+eTKcWi>w1*raS`t$jA$DhEHakFIw^AnaFloJ)1)$z%e~Pn zr>i@0H%jtIO7ohHXo;2A9!&G*FOU0Cg5!JnUOb#Cx2Nm7+VuMRYwFX{VHM1L7mwZU z9sBhdfKg&>70p{^sHhUX>{;y&LvO8d5a5{3P-HDkywMSE^#a+A}W;p?S{6I@J z*?DJ@vEj%{DYXg@Uhm!ne~4_6jgE=u(;h&LE!Xfk#%@W$F^qGbQ8T~3e^h#<+-QO) zxLMd2s>sT+^r**ian(`I&<)5eRMf(ppbBPp_Unp5K zT}R=3%z+-Uv^;opmyY(>13gvrgPM;-zL2}dzWnr%k5i9~Lc&o6;4yeThYDCadvi)Ya`)@xkcZ?_FG@kA%!2V7!E=6uG#Q~zx88eHk@Dkvt%|zl1P{hUv%RO z&wBP57!Ca=Fd2USD<_LI6s`pv5H3Q|;yp1IL&FOv3=^E6Lt`eAuo@;fZB5W7z-skL zT-^J#S$o9azz~s@ycC&bHl=jh@4+bf?sQ8v*Ky|qiW4u1xn?_lf^*jN2=3FSJiv@{ zhuV8LVYq5Le)0@*@a@1Rk}UBE3~l2=)NChQf+N(-Q<51KfP*_X1BSQEj_;%^N;!yt zL5(z~Wl)B1wZ+sziP+aFzVKByim{+`%qfiR&W_x2nk1Z2a|>5IYnN8p&AEe_Sd@5@ z36QY}_|m}X;_JJ}`lb`E=%;E{&0RrpTcH>2Ur)n~gJAU820!=H7T(k02Dc|IrcE7( znh7-QW=j=TM%i-K-L-YR98+#ocU^ZYqfBGTbm}!A2OW5T6LzoV*}#3*0%9yJGHMJT z4sI*UR zpzYIfUzH%Gt?QSycwn-$*=g*XwK$1yghli)9z^R!I6(XY2w!&CiXqRHV?ZZ8(D|(m z>bB84=?>Z3rL7wjJxymvVW9VROEDVD~mwxy0lHd;yhei{*3$UHloUOh1W)dFu@WBdlffr zU*67dj{5z>l{87BE>2#%uWsC3e?V!_;{Lf{ zIMzcZ=qhQvnLF;JU3X=Gl}vkVoUUC%J`@r19XRh%%`J1pt9kbwxdU#d*|@s&{`%pg zB*u_R)c!h7*@s26ewY-Y%SI(nu+yPce;_Y*B6ke--CDfEaYRl{kzx;1pXMLPaa(;T z(5Z0~IY;k=*-k`8oAMi&JC=8%q*yOpDsT)}BnH6?PF3f%KDAc=7PykAO-%+yIyfT0 zVU`5G>EiX!g~mR7;1M2)!*Wthf0?vFJ#00Nb6Q}LD^qfzL2a^eRL+`gAC?sr`=+!e zDAm*rh=;m4i_8#B=~g1<`PY;ry=1^vcp1@d8M_mf!)!AQ1gV%hv7mrXJAzXEa~;+6 zz}7n&?81@nEjwhRUDE5A9g5!-9ch-XI(}nMm7)-*&H}c(Y7jo@T%-^lP8W^+FZ!uP z27D$AS*}}GMY>o5*GAkZxOU8O5Y~QT);U_T6jKKqm2iWXkj~0X=o{S^i%2Pz%FyuKcM%2Zm*$ViR zHp97Yw$lvB%*fNF^V|$WL^qg26iA+hn=eLrFhyC<)k!9`7F!z*U_#;sQW*}>sCkG| z$Zn>OXvewr(&@b{jo9Tcw#O))<+Y{&+o|~+=NLe}1_f64nG3Ek?YRy&j3kO)*-GHx zn3>)v*P>%H)n5HntD&o+S0c2vH1$fU$v2;xKuIS5^7|lDR|=W4-8%0=F!lUB zh-k7M8SzkWDR_45@T5sU!IFCHuLyia#j|0Do3t=HBDxRBRa7ved7q@NPFm_R5{X+r zzb!^xXr11U)@THVhidl2;6*X}K32_g0Xi^2!p2)wB`lnQ@S&)*pks{<5L$1bts%O% zyJcgj;$_u&gAF1d_2hVR{mSQhC_C(iv+Unt_D6nH&HniQR6XU@Q*k0O2@CYvYh9D& z@fkT7A-42Oa5{BtMWS=*V@}!&ZiGso-Rh9e zLN2m8VE>Ec`L?Jle{@;crCm7GWK&m^le#@RETokzs^AY;#^%=)b>fI>rG)7^(YG%? zk?h~*We0`;u=KAx_7lC2Ye-Q_aDz_1G6pR|AJS%O&lWwa7U&3Ru=3i201ot{OFg-A zNfaicEHupvKW_y|bTDz?75b;aIB)9~VNN4K25`Fqm-$yCMq33j7nCxJI&EDGUI$|i#^ph z(xg&f=Vq#@&zdi*7vu!!m`paLQ2K9>QO8|V=%b}NfDrGm-5%DtAIzCl`nZdx{?s+8 z{Z!=^h443*MA7rx)67gu5xK5Q%N5IAQ_h)u9aaLMbTg${) ztRLZIQ}_~BQ}q!he*)?R2vQA15>P!tMO||iA@WUI=PRUQB@9MQIbYlc-(B#ewK8;; zm0jA?3!L8foApv27@XTVFNqM~Onjda$luxI*H}R6+biJ*IU!So?XaMOgejQ|_$Ypm zq;w=SDCO0$^{Nn%;e33%hHuJ(3&S*?5^t0>u+>PC5|x%TX-6LqoTJPJ8l_4VDhe%) z%U92+KZg@Afa$He=E4|ryol zi=%Cdjj9zmE&*d+WTg+3xvHMxWMhzP>kl8j{>Ep%_xr-FZZF#2*^R%j*B>P5@QYbqjP?(n z9DZqbZhqmy#Y>m3T;-fQj2AIPIbn71^N1WOWJ_J0C2n|@hNrHP(n*vesR%{rK zc~Dc#B;L2K1;Y^WAVm2c6~sN4PL6EfONG>qd!3pVH)RvX`$}B^5|MM6_0ydg`Vobs ziiH%r0L1f^HVaAHy(ZgZT%Etxt$<4 zPgAn*Fah1cnye;g)hiB-&ojSTCEPfZZK#QTX_pOOpRbOGyS$zBqNEU2Sc7Qv`1@Ie z!`@YjHYMnCFG#ROzQY&bQqQIY56T&kzKziWZARp{$05Y@WI{4m%HU!@s0@U&PpEm3 zzm&_XDS)?C(7MKY8v)9WBIX|+|HH#!bPt!~Xo_y~#CV&FJ5d5~L`|tHAqd2Z<|34d zR5hg+0an^3_n^E%Har{}@eCn`#XlV#PBWt8q$Azixe`Ny+}4PNimz|1t`oG<_yEEm zrkbCQ4hMt*8%Jm^8BR)L&Wp?&@v{u2itK)b^$wGz z5v@Vd#z!;DkCj}J$+JBfYyc3>3Kb-yszFKw23=R}5Tmf5rU_{$(CORo(Zb85+7nf- z3Igx(;P!lHAfO#Ehh{_rgMi}A!a4LNI-_reqakZzI*O_)RL`zedT#6pM$6aiqpqnd zvyS>jyC1nYm1kvEUB1keNHGGoW_fy<(r9C^9c0V{S{zTPbLY-c#I_EO`ROcwqAp$Z+i0ycnJ zBfjaPZm24_^>Ce!R6e*6m<*xlk8E{5eOUwG0Vh#m6QB;RLfnSQ?(SyM;{!%IXapZg zkmT3{4XLw~f1NM|5_A)Ef?z;)O&}KuAcgvXqgizY=dez81)HHd?uTZ)YVa%{<)Y3# zfH;oD8Ef^X@x&W^dNz`6*tOlg?VJL$|sn{ zP0~#|vbm8v zj<)?0^;>N@;)lHT$F>(5s(uIUlAg_7(i=1$0)v2}l}<>@*7clSo!%${JK}%= z-gstY0F(5#t%60N4AI@l5^icv>egFoUb2}J{H784V)lAwwgv223m?1}?k-rzI07Hl z_Nomzu;>9wwN2hIO6xvFaS@N4oDiTgJ*^jF-t+BeG84$CtM8wGjL2ZPP!Q=wrRV9o zdZRI~COxJrdRd~YyQ2ZWB%-^ZCy)CvAZu-x=j85a;Dn?S+R#ie8}Nv^GF^DD<5vLT zBtn3*;uX}NQqtCXk!^0eMnLWYFqiuf9J@`TDGH3vicLL@#;r-?mfbA@gI0w&ovGIC zQIT1vkmE|Pn>?*TRb~$9DC6SL!TFqzR-B6<0aY~?3GUYTf37w^v1OG}hirgQc3lHN>pt}ZO`O4hkLrxzXF+GMaXcl|N>GpVK4wdNdT z$bcTvR}`2XP|Sr(-gnX+GRJ9*DngG6UKQQ`8nP!qs?CIl zd5g4=w`k>k3mI~zHkyHdeFNdkRPLyNs%Wz>lBS9#b0^(lT$MZQsDL_f>xd3^R2_g5 z$R#_}4<4`{NBw9Hq<3a3dneslVu5d94&%5khLgzt2wcl1ZFq*T(v#Vc8R094c*0mbFw zraW^Fq-cf(#;vErjnY)xSroN)d%YH2-l#U!tLnh6f{&oi()76`TS;11`Zq$??P5EhFB#wRab4&gW}7@JtezwA$%XRAS#u25fM1jZNjAI#E z--=^+-eOsT=EQF1PHd?==VAc-BAxRD2p2TC_n zjS{-a#Fd;#{Z;H9iC8R9`2C~7;72@qSU{0pXOA{1nPC%hNSD73qFkUbUV*SQMPiISJN=dD|f78 zLU<%Gm4$DpbuC!AYhqAcJ5D`KcXz`$p@WX~)Epy!Yd0MXaWU+)qFc^!Z!S@U0TG06 zCsc1p#t^%ybu6h{139(?GTbt~!~gG*!V$=J$jc`>>kfAq-tgx$X&<5_a5yW+QXnI_ zr!16Ta=LP_hy#anRNGpbDeVK^c(uqYR603s>(nYP4|Ey&S9Jzx*{ECw_+!?*QZ&1+V6=3*~qdFqw^aqp%lc zt?fAK_d1hrLSL)k6RX0edg^!tb@nkk)c^{@N-j_{<7n$JCtH*!-n~}MlrDKpn$Dys zQ;G@NG1?!g%830|YfzXrN2s1;qD)*{aGn$KWzjIrV_Y_VPKjaGm>7#x4ffCh@+R8@ z)ZR21SwZ^Q$(FL<_WFZc?7;iXT+KB!{ILWpyC*22Ivs;IZn{mPs9Uu0(UQWdc=*s7 zh0nh=I#V_wwZ-bp4yBzhqM3kc7%nngu*rvR;x8fJapwzpnyAS)J=S>&YnYi%DI^g?w2!g=LwhaK(F7p0eg^-yUgb8$>6iJ{F~Wr ztKf5wXIob{Ux7VDb~9tA!&%u*B65QBDlc#u%qTHxwVjPBce3`VGo+$32|RQ}ox4Fm z!n)&!WOM-KX*GIjE=w+=e(Kx7z95DHJc0gU8ZYS|Yhi(ubtah27(TR7L$8&dYTz&a zVn+dXU~CwJn@I=yPLumhGykGZ^OP>Jkq$nN4NrKQ*x}7L;j{|DYkbxrQw#xcosA{q( zt08IyRo5dUO8VF2==O*Os|gCo%A^Y z?`1i`7qWO+D8}XSvL!0Hy6h{NdVA{tAY*R(1) z#6>dr=-rFI_AmiZG_0m`Ey<0tq}5(?ttYbLmX{|d9=;+w-DTEp@t1p~-6zq3zDSB~ zI1Go4!zlG@u4~j8v(tkl%FHiGjvM$Hi*e2k>jd2^YFU+LNz^sM3(Xiabmgq)b-L?A z?~f`B%(Wgw$mh;=9ceFb`5-I~)nPFfe3nm4vxqjd(=0K!=gL4SV~sHd-Aq1SD3pMK zpq4RP!riF5myZT{8~QkDP-Xcc+d)B{JGJ69!XAbs0Ii9-LEeguGMx?!(RZc|ww<6T z?mmNM<?cBPwH;cbwe85q8KTCJ|-1IdSuco)#8+Qs#z7i=HgAZ@Ck!C z+O^QzI%V~^8zISxP^{K{&27r%lQ;UhN@u|OmdCdzgN=2+mdU@`rzYXM(sq|XnIADJTrZsQ&# z2!Rs}W*Rp=AxN3>E9E)27|mN~6!{^Sxd zO<4)$FNV6T;0E!&tx?8@fIDgyo=VwGluC}Wek-SYABjSxtRto9^H?o*(_|kTpCSvB z9M{}*2EB{Wf_Ec1Mbw8@?NSEI18Ns5uo+u4D||@#*j>u-&{b~enMW>MhxOJhGU;k z^Wu*gw)s*Y&Th!{dYIFlkgjXKG%kk#E90k=WfLMRWs2m0t52Ae3hkNGPtfU^#zN@;0 z(TcQiV+d`+P3REYIPkI?>EoeR#z{DbS#o*LO2Wdl0|PAB$>~W4&Lh&=T{p+FfEX-^ zg-$5r-4hKKU^WjxHG-3qW>|JGYqw2!!h01zbdtL<}!&(}JHF6SIENMpoh z8o0XMAb-a2_;Rm@Ae!AsGx;D)MmSFONwvNg4|TFzCXVy0mUOVjoX7DS(Lu{gkwXy9 z*KxLcO`NXnx@kG8W`FCliL<8OO$FS_qB>S+`H&wAA@4dFHrQ{N-Md+T+k@E97jv5( zOGi^6OHa`uC~(ecw7yiCUF?K9C}7TG&2;>zWita6nC|GM+|D~rXbL{#kiq0sp0r_1 zNdWZL1EKmCBmu)QY;VWmG5wu1-OE)!-isWYg;BX-6LD4`UVy}Fw~r+6YElO#`Yu`KEk7Kc%#`Z2bmDjoBM5xtpWJF+Yt_fQ<&srVw0>01W^ZIhR}}gN^wGy$cnN zT2!SK!{-jS#ajLt$09gRmq)n82JCB%L5$e3Y(fkrprN8D1Y2qEa9X3CZ14yp$NFB6 z-f>h#>tNK+qmH+x5^?FZ(#bA?{h9Eqi@h3#_LC`8ab7nqW=ur%z5t^SnRmvZ>)phGk#h2> z9X>LL>yb}_Psah)2F0HoH@hLO1CA0EVgd8HcpN#6SvF*5pP}=k#3p@eWhZ@{^-w)E zM>$D{GD1e%HorKEv#9sr-uk$Jud%|!T;HZG^V1|x5DX@HSFQT5cXVZAKH^&3{faGc zZ(Rkm?OAN)$ip^%OJ_;KlkFshNQT!DI2!|4q*n&w#{%=mgRHHBX?3t0L&D`0dO3&+ zwRMPl;$im6i?GisV|$F0s+~MDZ>8C}u?8g780(Io8^;o@r^m3A^s*M`xbgnRnrCCS zrpudASd6mBNwT45@y1$dW1+PxlaR|=$6ME$(h%%;9TniV4T*oOFEw@tPqN2>x@o>o zBXo+OwWQ~49V~vG2nJi*J&vaN#AWAqN?vk9eXowZkZ(TjMlHJfe4EFRvoNzBcQZ~t z&M@_?#H9zNxzYE2x#|LDh}dqtLg-IU1?QfNQOt;N#D)A&lbnm( z?q7L}>aPfv`>QI^_~ipMr8_Kb{ot!-r&Vo7vN)Aq+C|p0JczrioB)osZpW`{6hc?6 zclH6BdLLjJp4|5C#+hw59Tk+W1ElSO2bFHjRfyes$cT2bT70z0bcl+$X!xx`+MAkb z`v;rwk=Ovo3Fny~g{eJf4Lzg(c*vd$uWCrPD~NSvautw~xT*DV5GHTLoo?$Jr>uTd zZ};K)-}+cc9Z zOjO$MMVanfTXKYWm`Wp%uuAIUKJ7B3>;N|=aylNXg>ZH%kkNq1KG zqBMHtE>&KEy5&krS0sD6VwDG|uhMj#CBdm-^Q2}8ElA1+6 z<}n*3jtxclK*2fM=nLL!tG3;|8H zRh>}MH@zC2ORjP=PJ6Uz0BK#bi~en$;*LL_Qx6|KDABo^rV+7>RMUv@$D-ERNZQJ{ z*p3!)o;7B;+r)lH2QCv#ESzj;oc@>zrc&bODXSqCh_Px2K6U_}ys@>97=jRB9m$y0 zl0WWHJm_urcF|ZK4*QgYW?<$Q9j>;LJQEew^r~0)pQvCc#llK`^cFVl6E| zgYZx#QPjiL%pAZKrwO|8n!ex1;-qi`MRY(5{)jG6lSQ`0i&`t)kFtJvI1T%DqOz!k zg`6e66tU`oofShfURqi2M7U*bvc6l%BCAWSw1Og9i}AXCfZB~@BasFd9rwn+8L`J5 zc`{G>K1$*}$CyfUNgpJ|sJqxx1;bIkJB*V+(IxHhZ!%OaTh>fnAj2VDghZq8b-A|Y z3pc6AGf&dp=pZL5WNE^;swbrbBocNcN^^x|M79w|?Mov`=rvBo)1sx-menV5aWCQf ze^t}@1>+4gNbekdB~a8XfLh53`~9dkk%_2D<=9besp5T+6J_U}QD?J;jzXRca2l;e z7nv@qwRkT}i+FE_W=dbH(7I;s2O=3$ep$JO9R)=6NWOa+OIrmq?B$$<+c;mGnF$BT zUD)0aduiUzMl(xl5XQ;O!iBl3GYe5PclGj>*(u^Tdj^nf_F7$#VRN!aG9cR|Ld>_q zty1uQSQJr~IMxC$SR48TXGu4vXl}ZxE9(57F=Ac-g~sJ$PBH8#9@3@w8cJy?OYPHr z1e<1!DrqaGFtt^I#pD{*uuwU@zCbSUAdJzSe_C@p{}vcXNzgbpi z^BU19#1*tTOIm)JE4oxssBcwuN(CM|AGvS5WSnPTRk*vPK-rB8) z_g5w5CHHbaJy4QM891X(J*z7{nVX$2<@&iEgPy!>`&_g`g{M>y2R5H8O|2mARYe7T zLgIHcd+zcw3&mMai;TjJ^dp!tgvloU|AaKHWf|Etcs6JF6?(s)9=KaH5r{TrGy7=d zH*{=i&iK?Wo}_T!I*5HVD^u;phB5VFR}7WBb$$t2)RWkuAG2ksr`!N=;3)LLZ3 zw$f4?21!int_k%rSd`cEZ=>jR!aIC)Egp|lGq^C#5HhIumX_3Rd(1BcWY7v+MV%Ol zUj$D%zn0R;kF=Go7-e3TY#OcHovNv^F7uVS&EW26uoXFreyt#rvr2rC0R$h#gNq=r z>61LMsV>Z4y>Ru?<@u`@fqhp9KM0dvI=B(_!^+_%TyXEVLΠ^eBl7e#=SHv=&hd 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 z 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 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224192006-Config.rsc b/MikroNUC/20260224/20260224192006-Config.rsc new file mode 100644 index 0000000..14b3da9 --- /dev/null +++ b/MikroNUC/20260224/20260224192006-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-24 19:20:05 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl disabled=no port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no rest-plain=no rest-secure=no scep-plain=no webfig-plain=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224194007-Binary.backup b/MikroNUC/20260224/20260224194007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..4ef13de66263994d3acdc6894e41c936cce4ea6d GIT binary patch literal 307416 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224214007-Binary.backup b/MikroNUC/20260224/20260224214007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..6c7847e4536858b782658e1814a15bac24aad14d GIT binary patch literal 307416 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

    *YTFPH8wp#-Zpu3dSqgJW_)1g;KBG5 zMLC&R1*Cx4vfrmUO!t%AN>Ky%;2Gwt?BemFDkB3 zdp*Z+O9i-uNGlcL76G@N+u}$QoF%mKV_GQ*udp^8ukyi{viAEsIy&WKm!T^wNsjld z$!3CjW{R<-*Q-YP1c~P!T!jjrp0~HNxub9x%AdcFq zGmOZD2Iqc)pv4Jp1nx<_p`4e=+S9nDkm$9aY9u~I z_mkldy%zal)JGW%SYS61`psWTHf<( zI=l9x4z4rWv#-00r@R{OMJnhA=>5-7*(M=~25RJrth2$H56-7$iM`$X`yp@RRD39r z3}%$uVjZ5<3O-$Gwqz&#Z2N|6It5n0phpzh&JcW4J98}%Y(5{IWo_26{aCDD4*2A9 zazGt{{+H=|E|5Dg??be+H=^f@riBOWwb}GFVHuTUV>W60Q`x!gBH@ZSMtUPE^*qY5dH-dBDyh;FQN1*lPz~}28Oi@ z)=dRjviIpNT;M)9h&{Tx+AbrnyWU!zWT`$@HMkRq-RMHa*o(F);~Kh?$@zCOba;jR zrd9+W`1V;;;)740#0P#^5IFPayJ!OV6bTx@C{4qQD4?*>u&qJyK4oU={-#Cy+B)~Q zVeqBRzBWHAth9^eM#D>+H`BVME5)p*PpaB(wp6vAKlXPOP-l=H3Muo4Q1PLi-wWitGO8+Oc%jqF_usxJBcmHH+&U0CYGu# zV+SNQU-pWNpAWk~HJwBX1Z9fvp5BhmDE<+$5T1$mcXf0`@eik?ibz7;t)wZVuXdzv z$jV5e5^nLP`zS_Y(t0`_z&r{Kyd10wV07y}G(HBWzenN&@?@5_PT|{wr=zcD4q5OifJxdZ!O3+QyLyR4kp&~;*^XIg zXB7qfv3UJefyvgYz{F6&B>Yq~#HyBFM_O|Aw3#=(C23{Ee_C14<>*-`vZ#9|eZloQ ztar z)*x_O2W^pOJME59v|ZD)9U0t#9xQ>TO5{8*Bqy`+7Z|XCJ@D(pUcq+x`@(nm(5Sca zI#Q*fqREUlBZX4lGeJgz$!ip^s{({Gsse;3R6r;{qN*YYtj_~`)-enktsz1WPWJjv z&q4lB!oDK1;E5Oj3v|y#5n|TPXAQ>{UK66@6%j?GC}$GHtBS0*NFl$KO+dv>zYjd2 zLV-fhFX~G)TxtkBu;UZBXtNTv(mGKZVRT1TTK@Fxl?0ZsBN&V@4%j04%J_;(?$hI| zJClC;{nct?k7LZ*Ys72R5sjTFC?Oe{_r!)-Y{~JE6f9^XPjMA1<6N#;T3lRg^Ld;? zcQzhOOvMjQT%Q^oO~459+$#Ix3lmWmPR8d`3Cey@mpsPw_a9QDbc0<)1Y1MH#tek< zFD+qK>#WlX@50+z6;5rh3a9p|N9l?OR|S9)>;6xl;l!8P1-=4v-@dnl~|YKn=DC&xXsN zDI_Cq!7d{%iY%N_T6t0{pkH@KXD6t7JAqB2#6we76nwCUt!Q>&dP^z0=t*192)+Ob zFVLXHQN8cZYr!i$3SrwZbIQ#AQlf#4HY6yrKve9~D)Ez>5-COF&D| zLrP+c9F7Y5S$mBqlHw6<*1xWj z>lp>E*rfxq3|;`uMBGdv6f)ptMVYO93Mwr1{{H^{fP@yZuqly58S%))U0F#(`^Fm& z3w)1W<=_jWw&`bL@D)cPoQP%@&U3HAB!nm`l!nl{Jg583dHEbcf>6S0<=lJ0%cJQn_Ae%ur zzkI|q3kIAy+v(ekjHhJ{&&WUk<~A*s&jV;?3>V}2nXXne9I%=)fbq%bc^Y;HysuG$`=oc9u`oDr+)n)u&r^5qsmvtG;dCv5VKgs&WSad#+8nZ^$Tv3@w|p)HAawsq}m>xnqF z?ZF*VFk$O3O;xCSc2%hR0+q9Tno?*|af=%^sS7mteJq+@4pnSrQOmFw6%kU5LjWD| zc{n2|vV;#^1%&JF=-3~yP(%#t>gq!AuPf@hOyR%0A}fTEq!OZ!02RRDNMv{!+G2?{ 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

    ==ZFrU9PUJ3CA5-ltN>LK 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224215052-Binary.backup b/MikroNUC/20260224/20260224215052-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..9e846ca8b22fd5bedfa824ff52f9d543ff593598 GIT binary patch literal 307414 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 XTRXm!*$8oEmaH^e74j++<&FOrqIf{k literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224215052-Config.rsc b/MikroNUC/20260224/20260224215052-Config.rsc new file mode 100644 index 0000000..b3ba3dc --- /dev/null +++ b/MikroNUC/20260224/20260224215052-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-24 21:50:51 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224215237-Binary.backup b/MikroNUC/20260224/20260224215237-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..2dfdbb08623268e779e72fa603ce02686e64b8e3 GIT binary patch literal 307416 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

    VEj+Wn57JOzP!5{-KgmOh4Se-f>H0ob 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224215620-Binary.backup b/MikroNUC/20260224/20260224215620-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..7609a4300233b3d1d1c9014aa440ff04c8913e02 GIT binary patch literal 307414 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�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 W+VP#tMu;o3WTn}vkXNB7Z~VW6*+6Rm literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224215620-Config.rsc b/MikroNUC/20260224/20260224215620-Config.rsc new file mode 100644 index 0000000..50e190a --- /dev/null +++ b/MikroNUC/20260224/20260224215620-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-24 21:56:19 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224220006-Binary.backup b/MikroNUC/20260224/20260224220006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ac8e685d1a859de2cbc20c40d447f6ed9e70216e GIT binary patch literal 307416 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

    VEj+Wn57JOzP!5{-KgmOh4Se-f>H0ob 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224220134-Binary.backup b/MikroNUC/20260224/20260224220134-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..59c5b026d61e235bbe447394334859c67da7d3c5 GIT binary patch literal 307418 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224223439-Binary.backup b/MikroNUC/20260224/20260224223439-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..c219143be03cd1531ac3e40995801485e1072594 GIT binary patch literal 307414 zcmeEv2{=_<`}aBn&M{;RrHsi?*k?XRDYFzQQz3LlWXu#vBBV(w8l^%>8Yn6nRT?x< zG#V;O%FuuY!gsB64ymV}r}zIo@B2RA_wQV;z1P|H+I#JL-^1_z-D~fYa%gYS{X#4d z2LOapj3T+AVSd3u6951x0015cK9~`0kr8bbe%qdi0sxP~|DhoU00`oS8%2ill!Zq! z5v~UY2M1+^?b!eT6JSro0B`^W#DP5#3jhuPfJOm;5(5J$aWDW-U;qz9zyNM=aBvV0 z1~h;S7|_55GW~*N`DY%$!Gnsx-Q)#V6B-;5?ib`^6v6TdF=F$4B!!n{EIct>8v}cy z6c|9s!+!7_sPSMxPie$Pcp5Pdm&c3<2p`#&5MCXJ8|la9hB*rl9w7r5g#BpF?4}iBC#RUN63joRw z0I&$a+Xqm=0DuqxfEXCyUlY8xr2v3f0KjqpzzV4EQ0-R$c@ z?E?T_R0dk5Jly6FjV=Iw4TAmR0ay&Tgu-3J;36CVJSPGGTpAaENC0q|Yyg%3fU89S zhynoDiUA-R031b9D8m@oZ5cdDJOF${TM4)Dz_4=20H6U9;P*d>ZlvB!{1v?+^7V$n zqmZZwmt?@=khunA9+~+=y`lV2Zz%swy-E72H%TW(7)>#}cpHJyfbaB1B$6BMOAwB_ z4FesXG_WUX4-Vj!)dvS~;^N}s9T>n@k#E%d7fpDpeJrm z6doS+2AVp5Ke>_GUh)gtZs}n0f35AP|0lIwAXokk7c{SqxZ!1ga>Erl!EAqSs6kXH zGuj|BfEyNO09D|J8lVbq(IGhn(f=C_5cu<-YQP~m1rfdm2=)`keHM>16d+*`#R_8& zTw{Sf5ypI07&kO>D1v^!1KiFIWCr>1m~1Ya=L5q%jCU~D!4C|EYQnY^f4d;Sq6Gn- zukOO&Ch$A_0Ivq@iLmF8&xCtGOn}Gm{|%!&$Cn*q#18P|28DYEhlKkD2ZcfK(mgmh zXd^sd&*0#onXvtVAH4*hO8@{H;W*&+puhkQ_Jb!dK?9&6heYvs6Lc-?Y^`QHdt18L zTIvns4k^Jo{W#v72tSV5cZY$e96pRJ5`_?k4`Xj;@%1RUp`%Rs?f`I{@Bor<91;_B zXE-=H&o;BS8qw7^I4nGf8OVkA#wRp5A_Ni2oGiRPC^?F-4FL#2*oN0i6}GDZ0OYUd zM!|?9xDhZG1r6X~Ph1)t3PfBe05q_nTqcL|qdsWZr&HKRW@I0cC82)dT*8k!VPL0$ zLH>#GBhJE$2ne7GI`Bt4JTffoP|xN^TAXI)h(4k$Cfh$E1R}=(HYYqdg6#|S5`L^l ztgV4PF$e(EVgNuG5V%?xsr?~ngt3nc01hVx01tkFK^F#ZJSqe(7C{LRh$J#RasZd( z9UkiE)rY=M10G6)?-57#fye)0AN0@rKs)|nAI#7Dz_EYd z2Mx^<`?b$dPR$Gnf-VQT4vx?*z%@tcW8tlo1~6q2I(3*vKu3W`^D~H{U<;Ew0P{yc zfTtG5`PU8baslA4H=yl_3jjcI1ep+YqbL~w z_*x|o07?M>=w_f#K`8@(8Y}R-;1&QVRRBz_`0|1&T^n^43@M3f* z1HPwr2LOje0N^29`@;YD!Tbuv&*ktd{NWcY05J371Pc8l%)nqK8VmsLxi&x3!<)i% zOciEg{214b5`-+c=JOl(R}MRB(XS4hZ*u{k00A73?061l30LH_;O#!$K_pX9FR`dG?!TH{cc-0B*vyI#dinpGk1{$#CHaPbmD%9nrQL(Y74XwiwYiAJMiS(Y71WwjI%) zF`}(IqOCKcJz+#!YeajLkfvE2!HwXCM~863qJ(ziEM#P$?s^K_(A0<8&>R;Ew?mY* zK-lgb92{f`+kJzBgB)QSQX_0(yMJ(SFhJObuwdwzXQTjdM%feBV4zF7fCeBL1Hc9h z0BIP3@lU`2)J68E)x? zi#`;)|351Mp&-U~4m67@z=tsv*2aBX}JM3g8t8D8Xnm;0{TcuUZE|$&gR-{M%)U{$DFo z89u8Q#0@tPvYvmxa54Wp;bQ+Y3M;e3FO@?p_IY~Rq} zpx}tGA^9%&+vO|r&y(+eNO`4wgTuo@f`=Ug>+g^)YD6T%!PxrG6R*gBMt$W%*ozG! zLIQ%BoFVPy{2dZTkCZS(EdOgItNBsetOJ0O_tKUC$26Q;p1ksN9d@Z0u8b^fFV6<|+Pg;}#2T;KrE z5Qp;yjKagCoe(&S0umySiV`sJqOb+oTQr}P;FC2lqvx}qE42Cb6b+yW)ADg}p#>K( z9fB-{hFBOk)Q=f}#QoCg3BPoD^uK(10wlddnVd+D5x*)l#8!C;g$37Mz@9in#0?SH zQh?8A@HvwCXg-;Z$3TG$)7g;n7m!(enx4;R$-yndq!vu$@z-E39~u${?~;Ix6MSGz z3Z4XhAonB%1T!XJZ}iA76XB2rvNQ+?_VF7g+#nkTKX7dzB;4RU1wP+CJP3XX1x{9h zoT5l%I0508$-?{sy~DWSaAFF-XaGO%{H0*+4(y4Lvw*W>Aej%VT(C;V*A7Sw3Ff~5 zJd_w718IFe?-M2D^#Gnv-@(CXK-xkB$MXvfgsvF!84+RJ&><={Rd`k?oS`<{XQOaC zS5WFPdMN;olz#VI>FN3$z{pxC=UXpg(+LAkio&+-U$n z&{$Hm*;?<+mz#|%bQLxA<9rsR-sx8~yrPm;UGMRVRCOAq4gf*Majfl|qwnSS=R0Iv zqpgkAfch=M>l>$qoU+V`(>C-FV6Ev!)LKK{zx`ojhQbSSWe^XDU^-r5*5B| z_{I%uT5tl@fQCRe&O4+tA{F|QY|>WkBd0#fnq{duz37ExdF77k9{DG4HV9-B<)zj( zbw-=g)T-Rn^N%M;!qMRD{rp3NXS-OyYQtaMELcSwzFFT4NCXZD`*lDuCuEXUmiIrS zx!Emv%>gF7-pz-Sbh}SX@!QtZD%5YOY-q;Rv*a?A3ZY!dZc{R-fK@PTkZ-Ylj+ zq==yU88Mm6A>MeXCJEQDJSZ~6)bo{+ukw5v6!OzD%44(?OddZeZit#o!hgB(N*Vw# zlud_(2J`#^_)Z3Xo(feMuAc&Xq9ULBhn54Ul#Lm-`~j4<(9ED3zNxMAT?vR@Aw=F1EncHb64$-=b-uqU38fJEkL{t_Nr=+0545&)D* z2q;ayOXQ#DlmyVg8iho#;6yr1NCXR(FTU)P^!53XcP8FGKAkD7X)tNC993;7_7}(SonQ z5N*I>w4mq%>p^(bDEJlLjG=C@MD$HJSb+Jy8+y1KN_e(EbVL838>}@8&W8S3H_W%) z(ENZl+zs=yZrC4m!wz@D{;ZqG54wpAcM~BBB>9JH6aBUuG&jLziT1!Mn;w z5=|aqynphV5IuWqy}zQ(l8!L0Dv^0kOb5tBmuQ>4+f1wqh&!Z z+CTeEz%un(>~b&e{>>{8aZ#Lp@{HRiSPTX+BuF55QH%>#R37c(M36!x;1_XuEW9d$ z3^EFS#mMtdqwZ#fs47VjDF_20A^eZKk`x(!B@#H4NFCQ-wkr5T+j|Pnr6`2%| z1)3NZz)qDLEO>UfV$tG4-#*-UttD@F*T+cSwPkF0Vb{jG`xz;fU)G^)nMCMmpZ(z4 z{QHF;G}QazE|Csa&?197$4sa{t8PMPPZsH!9k%Ggy=$EHawYaBryI`jjb2MR(>bkg zOpZBX%D=Yp(kRp*7K=fnL=kCGjLUd=_+13SpiqOzc(`E{RuQX^b8Vt~>R!8Q3j51W zt!u_dT)P}xN6Hc70}u`xiLyI-Dc0a_j|=)xw~|Yjd*7=Ucf|4!r#7>1&pw~7B26(? zG(ft>q!^gyl%#r{JcUNac(r6NOL}sy{?jE&_CEXLUhN5;6+H>tFQQvqPNpK%O4Q;G z-3vE@H1?(IOnx^oWinra-+-I_V4B@xO2V|L?bc12pk<0BD$U31l9R&E!y6 z2tuULNCX6-vYAXWiAf+5m_#Cn&SlULgh%GF7;GM$LgXPtCJmu8nG_C%N~Nv=fbc_= zUJFkV1%QS+lZ+6lEGCi5qq1piBElgfWEz*krBaww28oU=hNw>H@PgqSGw3e@;H)bb zCnvnXNn(XgaujedvGnutv*3n?tJ?;#<$;5X$&w{Y3^{&2er#@NxFI_@a4hto!+Y5T z1hbd{>iiQ}nEirBEqAhl9(6^LTeuJOu>5BU2JmR;R135OPL=tsQ$-~KfHzHs{ujDa z6m+MmLn9Cj0G{8%%#a-#ZWzK1^hSog>~Rc|fH{gJptlOVtPF0-Q`a!Q68i>|wE zygCz+62xLHD8=6mrF)DcyID^?or z@vV@cYeuL90zu%Jp=%})MtuEG3?TufIr73$A^?+sk_JcuN*tYlLV>0!&tyXz59HS5 z%sV(IdxON1wCmaXI^}L}@j&6#Z=yEm%|=c-eYCjj2j=Z+TCdr#O4Jm@<8R+qS$Y1+ zttpGGo9^?jiX4yBQQQ!drJ51jd2&V$?(zMjOC=ei+_;&ZYG;%_6`bqTeGneEG-|tB zl5fxgE#j>6voEx|2R4VCUm|n<3+hACqXU*Q^NINp%J=SMpR;MwS=7CQ^vM>taBZ!3 zv2o)0y$5I7#ZIeo@D7Od+B1u`F{@s)CGfVw*wjTg25uc!;3!@7(90s8f8W_#BVk@! zaMFzUShDubr}%rP*Uz6`qS9)sn;r6)fNl7AO!2*)_-wHQ9Wzb5O5$?TE*;fD!$&l7 z*a-8x*pvKcu?N#QhvIt2?lkXhPLqntrLD(I?zkXoFf?gll@Y}iKi=V6{lh@%-^ipL zoFOkK-rHcA>EKw{{p1L?CpsFJGeP;wtVxL%3`*}^9q2Asn}6d}VCK^Bm)rCTWJ{Vu z_Uyf7m$H5Hx{V=C1=8crZO$KL-+L~$uqNmHE)V>>d#TM%-Kp%}>3Ma)#ucyk0VM_pbR(liV(tYIPXsCRk02cHT5`+tU>@4$$7by&t_$vGGvrs9QmYES2a+ zwvV4#P17%>I#n6Z5&dY`dU>9008>Nx9`W_%4i6+2po(J(b>+) z(aFqdh8dAUB_c$`!i-=*_yN+oiA55y*N_BEp%7_F_M8=+*M_L>Z0Drz=wzlY5Rf{Q zkh+B#;V&KX&5trHhyAD7!5wLit`&hgF-zrK*SzcgeE;RM4QDe7-Y+y89a1L;dUeE0 z=FvT3kImh@IAhczvvd!NN^eZ>>56j`kO9{>m%C!OHY@Zf*x$&Ld9V1oK=Um@QA_5C`lfmp5nwAQ&| zs&jL^J8Z3;<0hw6bjxRM9X%D(x|dP!CrKe(M7T0h@2K9L*y(ecI9M<#nu(`9e*t zG!DP5)ueZ2oQ>aJ0m4c^B_Ii?<%ryHMvp^8QK&&Q3XDkV!;@BA;9Y$}Ypgn}M>~ia zf3D+}(l@|rwx+YXaz;yYP>XbLZ>d~|sL}?;ACMcLB+$kxA_}6oNunqb5ityExP?X{ zhuSCOc?r(ppun+!^1<2jf{fXVIkinLx}0{Ug%`9a4$9!=1O7T?D(Bo!F18_1n5Ey#GS)#2BZ7!?(EoWtpOxYaX~; ztm?40bM-!4UQr^VZs>MraAwaQ{fC7ahp!vXobn*=LvV`T7i9W`#M75f#%vawd~}t6 zB&h?qI39D$dR|)H_2i}WK*OiYr81%Mc&vBT)+|F}L~7NJ`FH0LmeWx2$9REyV~cqB zz&k-{-KD)oD20jzt{l{(*i{GUPP^B7S_dw;qLUb3yL{ccoSlv@ucWlomg)Dsb#bSM z$~*+}Rd!)@2WgZ8dhvdlk!Ko}W729XtKRrv`mydBibaF3r$4Dr=xOVA+oUBmK|e#= zu5$0jmfDktR)rsb7nrlX?(@B~iKe^7wm}FA9qKRyUBu!u?~uOv?dgb=-=6Nbr!)HP z>Ha_PbYHPKn~o4EJO+n?|S7SPUkGPGeDsG#Z0OVo+!d0*y>1 z@z`_%iG#4HL<*C^$L2qZ)qHIJqZlo~=4>8?#X+b<7KMrsd1M-sMW-M{Hj%_;^AIW( zV)K6idHoETrwhqWQ6brh2Tmqtp?*t)gP4-Q&culw93CFVVFqxefP;xmuqBhjiH3Y9 z7T5-{4JSd?(l5UkpO~JHS=pO?Zq4XLag7p}PK;3yseFCu05*M!^)jMV7vO1LTkjW0T_>x2 zvgX*hg~jw<^t#(M4c20f;?vqZmt9-dS2)QjcN5ERuC@qstY!SV$@vyrw4NL?j^8m# zuVP&OD^JxESy_lUzo1? z?m9pD<@|zE-qv4kUsl0P#kbiK7Wi2oe`+HD`>>SvhteIaTaK*leJ$k~??@7p@zFi; z=EGSLvmo{I^vBYT-zg~{s&23IjK24ItD6so`EL0XQ9^{lUiDN5?yBOC`!mlxd}UN! z=iXTrzAmhoZvI##<`X*NRR6xB2S+|UXq3Ot^_{J~Ck-db7NiyGtoYoz+x-=7 zcfs=~0mqY+c9}ey;1Io$a^D-hz4aldYw~i1FX-31Zw-q1D%EMG(G8ZazvKMQui2Yaxzr>^ zyty*YoAIJ4qO2lPnRI*dTO+%}AB$ezb~tc(=S*kOin!Q&IO(Qw1Iv|89rF56t9Z-; zFKPcF&%bzkBDZpBN>h{Nxdk6zkL%%A8kJi4^F#TSMouPtI+YJqf1CN=>5P7x`EN7- zubKH*oJOV)$Owx>B-6Mo2AfT1Q&?mk!lAJ!B!ofW(ICNv&>37Rm%^lyxI`M6!QqgY zY$k)ipmRA)K2H0QcO9-OqY-}H_?N>p#9V)j_d#$r`d4TW2rJP->>y-IqrNFX&#_Yh z4kj)^eoMLG!RpRjwr@}{oYce(Q+F~nGt_|9Xb5j20@c5w9KYb8ujp$WL}|iZoI@kR z!nqvv+1&6Y!J+=YRGnU}G&lpoveksTkdd$q4`JC<)t|z$@2k^lf-x8f$6z2FgMo$F zcQEWcgkh(V1ayu7hGDRl7e>Z7Sdm^n0*B49BWNP(0-rYKr;;M*Alh&r33=5&m)Fq2 zF!E!5Dm6X?qZ1G!kw8RfB$~UD6p;ZTnDFa=eSClAm7Duwb3)55zP+xns>dHS`&p2w zSXrQsXWT~*gX8X3=Xw|968AG#od}XnzKfu@etO_HZ?7`La}g){3d-%!RKiU9vb)&3 zvvgb4y{Cv}-?R^_>pJ3a)%Bix-j>z9T?M|iTFGuYRd}5F{7QaDi16ehh20ln#P{)zVQ4A-IjDSGHEx%>TYhIkA8(KBsX@INIGe0S*M+eVq#Lsyo zy6?bX2Ce$wK-2M_?FLqfYhIY+AB3ZgKCXVa{nZ(rTATG{Qr6>^R4L?+E6pWb&eRRZ zkOxU)ChmJB6@GHs)+>>%I$Lsh4bP6eH}k06=DIR0TW80Q zn(l$o+#`36H(z$<4b0_YeSL#1N>3TiXJ*ty>g?KKAiDp0JL7Ia-R>O{I%tYsk!i-u z&#jp*DPyefpCtDzzs=b3i2iQwM~BG}d_iw9#1ldfG6cSU8~2|&>tAv{zm5C1asSth z`zz$4uqkvhmCm71coaI9%%E{;WDMC7n& zR63hXM(A8VvXI}<@m-NG+CS_wFqIQw$dU7V~OogH1AoQEKlE<{`Wtq^MQtDw;0 z1)SJ7xa_Zs*ek~HX7LHJyMqEkOh)hm8gYocUg-Q3c@0gr9#O%bG(02&M<=rpgqUA& z&{s+ah4tKoz&^)Qgj$1l4c8BMzWHudCx5pcB z@b$M>@4ji0-~OShy#8HH(ft^juIwb6$BZjyjK>sv?>`&6D~D}PUso>PSj*zn#pQ^;OHp2wraAS@fc)E43Nas^tEJXHpL<2t#~L^HMzVtQ z^fRP^V*IvpQ+aIx8b8^9s;*;tom2sNnBg?1w@=%s9QM0X`c9Ir;Oh4yDOAE8; zB3^QOQ+IG6e74_J|8)yDH(tIf`Q#b#$j!}D=0;`stnD;$9gwW{lU9-L(w^u~3j7#k z(;H^-V)>|jydu42#6-5s>dR8)o1Kv{@`q|-X?bm)#sQQCb!HFb9_QOiJbAcc4Sq8# zwS-rtopLMjRMGTYhV&zJR-2q%#*deVc z2H-r!B^+=2(02aVxJ}fSxtm6HO^h99uXN^myT!!n^JdtTyA+s7d+n?Y52+n=a+p)A7bALHa9J{R&N;qR+b@oHVn_dBwAbJ1^{d ze+1)r@PWwC4Qtm? zkDiwjxxILO%l=@sfc=YE6%VUdhDyHkkzFmBDQ_1_esbpC;wJ|eH#{p1ST|M9ll%DW zJh>AV{(~Eo)H%@a=t=lE!Ac(yc*moW5I znUZj{eWg!Q?Y6n$MWx$UtR9Su8nYmJ=0d|wrbp~(`jf9;WnCNP`H|{T`BYmQRopOE zEOQB%UR{5$-K4hn^z@ra_k-i|4W5*uKlW_hQ9^lq$)|AD%zWJ}t<=E&+Eq!hCq1jF;l%s8<%NY3 zPc!W51%^t^= z`4ws@1dGm;@ei(~PPJGxK2NzZ)vLt=fqp(wdUtS`D1|X+2&@10|NoIt_1pjd z_W!^A|8M{QU-AE6(>X4UL1Hsl2$9F3GnoVumq=if2t*>C$!4<yAv`vd#AZ?mOge$ZVpGWomqbBG zL=K$Q@N4)UW^_N!6d=JqGP8gT`-t>INU}3U|K2Idq`%JQF4*_Zh1r}br4MFvg6C!> z_^F(xAeH;>5wD*=H#>f4&aHu9Lb70%gAM7s{LKQ5B%r4w38)HT{wCt$dgi@XE`@R_ zSNdLoRp`ivK>zJeSlN*HNf`-&c^DBs=LIJ&z%LZx*Z;&2e)7m}L*Ap)Yfee@NyKT~ zeS7X)SQp82>>2Xw#w$C|RA+p6d$U@ijOj7gdU=+??#@)Uq*A+BNKaLwq3O!Z*6C(} zQx4bUD!5Ujc3~_!W#j`w8;_*q?e#CQxb0J~HHaCP(=_c@>io$g@cr?+8M&YLRy;gH zHM=Rx_G9UtnRR94-NN_+go`GC!)M+HOqZK^$AEE39KSWJJB7L~Mdx%&%KAA;dF;327a@EaNe3VQwH_Mj04&*LIz{i&=u^#|_RW_MhzzhfJxggSLCdBf~=DU%ND z$X`=&2b}%n+_d9`$Fk!(N)RAIl^r5;p&AbX#NP@QIy~*2|FowK>9>OYs|xlt0+9$z z4wXu#^XLSGOd!$OG!mUhVsM#c5)mPgNF)Y{OJWk}Y&Jq9GN@c0gT^K@*$gg^N+S_C z2tNY-$Z|$RAPR*-p|aRKA_X3nLZYxqOftgbP?#(-g+~1OGcPuzf9aW*hF_gorwklS zoWhx*JU?y#=bHkrV3OTrNGN{Yfv;v?8O6VEmYw9kKFiKvcv%0^G`nZ8zT1E#poL-S z2h;2}e9I&L;xs#LL`%RSjvF4>Hv$#TxFaHnfJ)T+y4zof^{=Pg{o_XbS4E<;9p#uW zA2xhJ7X^Flp7Cf`bW`?84AWKllFf++l_nI!)fON3`t597Gqzt|J+s($2~p3rzqEZ_ zgJy4Ny$*A0=Lh%1_MkDPt0&hddfW@|^Y^Y;y-&t*wY5w4sfckcanGHP%=+XKIuAYO zlhR_hHdS4*@QPhC&IJ^A=N5KxXwjQ4v|D?{JqvWQV;#MvCc!>!ysPg^G}y)rubP-( z%I-QAx@e5l_R88(5jSalYgd=My<^3BANS@WpYl%HN4l#ux{1cMvZD|{Bo&XE$!V` zR_zZo+0UonEt4dwWH9j$fCLhCf z8JLNN7Q1E=K8z}nJbki>7N=PTaz@2C_W7Tla=9jY?(AD>-9BPtu1&RGDus%znEx`c zB?(d5G2ybzQ|!m5@8fC@iVvEPr*)*i;JC@DFQL~Er_tjhwuJTiZYa8OTdktKH*iSacGDKp}HjEEzS_{uChm^%T8w8T+3EPk5?cOyvwreygOY{WoG^Q{ z*#;J724+Mvnx!?#l44~=l?DJgfPF_unqs7~;pHe%xm0rYM9+{xz2yBzY_5~CmL^{Y zj&YghpHWYVYu6qLD6Ie3p0WBhR&n1Axp$Ta@8(pVc;k$0SbF;t`QggOS`L?s_3P!KV zEnt5o5jQixt$D!H;OP?YnI1}OO82bj*)`d0Nw&gC(y}et1fRPe)0VL(bBj&K%Ze52 zJiGU7)D&^a+SLr{iaT>Zy{ge0v(0vY{X5ya6WZ$5oOu*wa!BPt=fLuTS;le46^x{9 zU%fXuzWz{Jw1)kwft6<3u5-`MyT10^#O?-#X>a_)2O|3C5B8j$(CGSwt?@zX9f@7r z=8zfx>Y9Y@aYjwlWT}Nt=svYeY~Od+wa(RG#oQ_nJlVO*tkFI%u|!W!vE%ku=>g}J z=AN00ryA-XjWX@vc`dcn>z-M*{*qxs_zeeKS84p1`(ANjz0WK+o{o!{L(rIvS6MM- zJ?5|`$#K(EMqp{<>*rgpt;FR{+**N)@m`r|v1j_!7k%uz3j%O?OT%6EB|N;vU8@mq zNI6iy`@zdouPajy-O{xxFjLNZ>Tty4Lo6U{nHE?W3?9N#)&-8KC4eX5e%eI}3D ztZmN7nbWc<`_)H@qepJGh5Pt_XjD#1!S}EyF1plxdd}w?G1i+6H>MKDvnX$WUUypI43b6$X?aHF|WTb*Y$*F^Zr5gEuzit4YW>nFhXuT+F0D4dYO?h zY2~QPI)zViE~dsG$Jq2ctd{q1wB*LtQX+AY$6>y#Oz(sibO&eCy5y|PD*nCw_lOZ_Y){U}@C1P^A$Ihf=< z_-t`;$J<41-rJWC94^~=My>D3dFdO?$cv{Rd$DV2xoeP5H*YsA6{}rlboJvlxvfeI zCb^~?x+))x_OJ28y4z2Gy1pbAJxA|cm}M8npk{fW`{vrNS7xu@=LWx6wJXW{j_Bz4 z>lSlG=E(B4-VjS`mM%-2rj=^=`FwtLQ2T@|qfr+Ym-sl^B?Y|lWHVGVL<}iQSKlj} zDQdH8h{k^w0&9vMJ4?`pSQgc`i+SPYCr|l1K zwG;8QZhd0VE?1-6UzMyG629n=;>DbUSGS2J=hhWI%9qOPjref$wN$@GWyu)Bkl^wY zF{qfUYj^Ft95N|%Tg(>CkSo?KFk}9x9;rDwgO0?#Uo31(>pbvuZVz$6^L>w_P6Qh+ zdLXgvrAgHQeA}NSOayUA0_v@RpTtQ|ij0swwk-EMNR4O?zd%azXWkEHXf!zMNbpb; zVTfC#BP0SDp}GIkG5!iP9a(q1j5(9B?4w)xOJ-$VT;_uBB_L{Dr$M9)5m@vsXunM=z=uwmN5s}9(DSem5 zb4+hKKKHDlhMf<(JCCTyS;c&P>g*G|Usk;>{p_N#it_Efa z-QkWK7BY`bUz=XH%YB#X$*udEA9Xb^sJ+v^uun$)LX+I6jFYpcpX+_7H9oNP^Ss@; z`S_Ug)!A1?dmc}muwaeHx?G=wsN0p`KI7s&Y4b(pfXQwa#8A*dsyQY9rSAMtnN<775Ce| zyTSZNmJUffpk8o`=tTiaX^qIh3Z+%I8f9u=6Q%BU-OP^=R#Ko>M_#dNI{# zkJ!<|Hp6`6(??M=rFRO2TBBFRcf0P0~cJIxUAbYJIg1>>D5|Vtd^xj*p=NeB%acY&J*+6XCEHRsW=d} z&RR+G@a9X*IJetx_4TAe)?{IJZlJsS+c=R@CzRXt&7UQU(^N4oBCbAH9(%8DfsN^w zx9@q8)?;HfppGf8aL_t4r=OYZb!B3*sY6xUNy46@U zAvtE$D3aI;*70PsG{va8?OtzmUN&7NYm1zImmsfi9<1BHGV0;`OWL^}+a6Smc0F)N z;lwn3|0Fs0FD2&VQ^Km~_KZfg+ZB1ixduqc|ACHXyP63$LF?H&)aaC zb%uNIKr7ZhZ!lJYglrWb)7FbJpHxCi?{L0iR`emgNTgYTxFh{t*5_lHAsg0`I59?U zc_deJCvE?PU~y$RYn{0qCB5e#w;ymv9QAj1tqIxKr4#%#op8K`>kz7M|3JC4Et%_^ z9(eDHo^kj5M_u-!qpB{4&)X7bl0E;r*1?3)qwjnshZ@gK?*05kWroki8)rUz}bj;T;I&)_3z3JDo^-E_&ByI0xdNT;Rj&Y%`_Ojupb6b|I zgKpB9`i?7UH$%1JG`cP}teoY0+G`4rYn*%3yfnIgORCC=oqAq0&ljc=R_`(EF5cR{ z^uqY%XMCPDe3=rvBR{9qe$@1dXCH=4MJ1H!W@s#)BX{U%N1*nEFD-?aMsH7L9yz>? zcR?~B)&8IsI&aLR{p(n3&YrOQbhCh@x4Z4Ed7*UA<2)sCnaAVUHdE4bKYTp75xcq2 zd`s*2qf(@kVF5{^S{}E?tjT$Nz4O+cWOhvdD^>3MTW_$p=8wB+Iz?_-eP`r)F1JZ) z`SV(z&i?J6Wv*{gonK#M-{3{r>9%4o`=Z(AeaHPyIlF#2n6+jNFW9%CFGfvrOeA~z zoMN$j#S@hW=gOr<9StTdE6}*IaNKI^ce}^x9P^NGugVfp3%|UtL9y3x!n7ljVKSC3 z)zV`Lnz8X-&K)1wC2EhHoHM6cpO8F*Xp+TR+}F$N?GD{Jt}w7c+qK#!C3Wk4b}EZk zpP=q$oP5_St>Y8+yxQUDh#k%G8&elvd_gF9GrgB{^r!WMgfzE&UI3UVrmpcD?Ij+`O zeeCk$kUAr;?eE*HpI;dqw+W>wVW8tIe`eMBESU$#_L#*k4myo%H`5q ztDak?`?@DpFH0M!oEN&%(bRX>xf2_`vhTb+Z?eozzBdNlY#t3CAsc6+Zx&VCvg@d5 zc&^Ibv$U=Ay98u~BQodPdM>tb1UF&swYB4udrt*n-rFy$Sx*utZL0b9C5k@^x!>Jw zK6#PaI@RX<$<5*gSJiZ)l4Mq^%wIbXaoISU8MX&4W@G1oTeZrO)6!89)ImEX&TZan z9l+H;Rj0H)+n;<-{B7g7g4rmsalVfuzNGG6;@jq67k;~&U~+B37+0Zj1; zx?1o8pR6XgKO--Go6T>t`3dLuzujyglkpn@|AxT7A@FYq{Evsgd?JHNVzIeo9uc9k z2n;rvMdXp`R34R%(5UdaeuP3`kq|14#%9wvG#-~rVNl3CI+I8zlNoFpm&BjY@gvv; ziHsk@E%-i683GLfB)U9g&Fk&#mWyV}-Y<*NYoD)C*2hFVK&grLQEHCpg>z~} zjp&UxOY)1heNo^}oU8ZL;|1C4!mK#rO0L9QyXms+C*!VRQ}pMBM3GxJJoS9fl51q0 z+j*gX{=mh#TQRMbYcJIMOj))Fq&;bHwxM%x z?W@kwx+^lJp=jInGn3NMqUiRBm+z*nWZijpe44z23{;X)c3i+)%^3m!eVr$X!)w?%Ot$ouO!|&mtivLy~LCi?2hWt(;;pF6`{N5 zy*fJiu);!ism8{)p?$ty-uQI{W|+Cv+PRxfyjHnR+Bz}g|no3mPZkFFYfZT z#0Qfp_}w|5)54Nnj}_g^61T74(vhKYnR9#ov#rynj^mgR!=6u0ElOrpzGFR046j@L z*1u@EVp8#!=tA{9ahE+*&X+MFMV@#OY2%f|Ld3UCKgyU{`e&KKZl=~pf7IdM5_w0C=r1F0(bM8!T&qRzeazj{aXtgek&||Xi5y(3 zx-dLJY18q^dzR`x_kCOE@K(ua`4V}J7oW_hyjnPL*iRAlUU$?-S*+_ut!cU0o@l>_ z)q$(4xMii2f@ZDBf0!p1hbn)1q3B83yJdkNM2^OJ`-@3j8IXT~-4u6z!?o8d0@x(% zk?d-8=+gTl-GQ=_t+Mw0f%{c2z3Ah3j&Zq8WF2YPZ?^H79LFhk;g#K{_kt>{sR0#l zY*ud9IC0GOgJZfuOtormzkzwuK;3xt3Wtm;;@Nb=8E520t6T<;Z@8ya|f#9Tr+BRrKUG@bcD;_=zWr=w$7=@=~p7JG3#{vgU#E+_a3vZ46gGz z`O&$s_kR?5bDk{@x_-UwnEFY^>$|G7Amf|oy1KS}5FP)j?#Qe6iSa4c>BsYz9ZU>6z;u-DUSoa6rI#(utKNH0&7aU|nDgao)8X#L z4_6Gln-X$#*Ni@+#zOwjcl>OE(H|o3ZFzIXpmBr;CbS{^`q|jJYI+0Cg(nv%>0slv??9U@FiD+qU zPPH_%qFY%b6odqe`uxZ{GR$0%7391qAPww^u>j!2RaM2~;LpMef5>|%2}T*f-$WZ6 z92~0f;~rM+^83-F3bHUDf0p6Dm;i?c;OQ^b`6UR5A&LJ-fIl~j^a& z``GYaotmw(nMCKbTue&*g)KSYPVS4e7l)-#hh!`Ib8gfm+p@JIZpNme@6awS=S|IL zOV6-LzJI*N%j2A-b52rCIqOkqapA-5S#^#N-JVpgwC22=RetwI*VZ13H>VT&(zGfr zr{2C?PF(oH`Qq}8s(VwB`l(j9^OFjzUNl;uIH!X3*wGiR(KR- zRtD2IBof+u?px;EB`L{E&U{A7-o@5Dw>CefXFhEfsqJd(RGDd}bCJk}Ed~0Vyj3e| z%PdIuv8~2;RTxbkpnV65cW(`{qxRWu^GiErIHB=Q6Qn5K?h)+%=-^A)`LorHJ5qRO zM5=FlOdB6uct1fRI^FT^#)i1!$^lGjT0%Sy4|*ov zOzdOab!--?e4u{qqrvvQ5qkod^*68c7A)mtta;~rxn?UOes|QuBMT(D!Mf8+Tn=8S z*c;Gh6u6V|DCXtOru?+BRed~5i5QiuS*G{P9HZi2(0sff$KCWD+(MkvD&DP)iWz&h z@XoHs;l&F^*^dv#l{iVhTDmhws#(9FVa`+edjE(~s~pSPV$PK}f3Em6+Igq$<9!>5 zHH+TAANw{TEn%Z)N#oKw%O_1&RO?-i(X;fjMXT>~9@FDj7cNOvo#f>1tno8L+c&D`PxQH$NUmC5h4HnpWe{kk?m3NwE41l%o+7j&oX*QqBW80gi zJovo+lWmT(Qv2i=DPvAMe|SYzwfit(>BWt9uI-;%kuqL^T()PaZwscSJ>w~o5_kV< zBBA%35%uE@ht8&>aVpaFON>59?91WsdRv)A5vZ;EW&B>A{Su^!h!%RYJax#PQq`*qLyMl(aiDh^b7zgFDz z_#Bd~XTp0mp(-nVKEAnI;ndqXoR$~yOGO-Qa%b#NDnpF>B~QLrnUp^`GlL$JFHyN1 zKdY(h!xAqa?Hyurjax*wn%o}OvU|4Yio6#YeK+I|P7<}ij~yI+Zl;__>w`E+Ui|bo zm(!=@DV!p0txa6@VCGZB%r;7gx!4Y4e@ThnODBcNq;qM zAW{(`kxZZx5%Tb>PKF;xupIG(`)oUc93lg2{bG`Mv%s)$ZYYNtIJAR=B-++_=&hL; z$&oJhFY}9IxTxk8qgy5#rr+I#ZpqFh&=9J~2w^@3^0CcUZ* z9#@v|B+p5bYnDA@U%8>rsfs@Jl5MIU?7;QAy>^z>8D}@mz@9#MB#r*wvwYpN-YXw6 zw?1?fyKb|7bWiT7^!D@iQ8&>&hd;>X7zR{D-bDu*2U>5ARlsr86kV>;)oG=B)`s0{ zxx|Px{ur{_{Rs=`8rGYro4y)w+h628J<3W`T~31Mr*hjmpl0&26t~(f^QfaLvrHqI{+?6K4GH(9k0+M|zPzGp->aHflXSJQfyzu^-OCTbHaX9QiPnW)UDs!(M{q#`1#x-`?n2xB9}OENEG@P`2N zG^{}gY#!ca4K@#Z*MP7wyTD>Fm~RaWi!tW)&FuG|b6*h|SzX-{U@ywAzwE4t`#AU9 zbIv{YoO93p)vx>gOaJ=CUwq_)&%XRyzx55D_tMm}m)5@Oqu==5AN&40-~P7M>**)n z|2g0LeN$UM_zlf>Uf%!I|NYkIrrvV#8{Ye$YTx{kkN?DDfBXYqvhPFnjhaUC`;O>PQ~8@6rwAmar;5 zC8NA@c}Ofy3L%Cbd`Jkj%>L}>Tue|cgFRS0*u^-PDCtoXY zzujx-+Y{nrLL3pIvL=LB7eZ_bAtE6}CWPn-A-07OJ3@#L2q9h)LVU5HisDOz5FZvo ze5nxP%Y+bLE`<0BA;eb-AwD96_^1%#?+PIrLWl(+#2JBpUam|kbJC3Z|D^hV4*4zL zfv?j-90J_$RR6zAh(j-ZZbekY%R>UkMk@PIY(Ksp#Mfbby;;5Ly z*CY6P6~3MjxNU(yqt5SFBEXz=>Bve=>O-$;^doz z_|A%WlUSU5JxKL+C3FJ5dq4;zm=TA?%b?jI@i@L-i?4@4Uk~Bypb$qN==N6IVUtMy zaUn!&quCu#gJdg6#*>(kbONya7iLlVyi*AAPO&(Njt&S>sfd>k;eADjp{x6ZIC`Wy zeD?CC^H**>ySQ+6gxY>oynOUi2#j z#M{*G0|G2k4+F@IWVQw}Yg=$OE@%s>L%Le3sCMPA*CJAN3|(!fue8?`jZ9xI(G$TZ+>L}3&yT~NPc zdcHV`8A9t7(8a@`3zn=Pg+ouqX?Df$1Q)m~`b04O#_YZ&$$J|F?_9$%lma&^~eaEpPeS!*6-ZPZL-V zgBz&T!$KTA0Ln)@+wG>`Y*$q~v(5nZZ!A}@R?q*I5Mov=PJ+=M`-m7iyze7KYWwzo zL>&6iE3dqA;3MMD_YrfvJXAUS5iwLbh@l?(2rUi+Dt0?{qvqOrTTSMiGnqAKGU>`=s}hu`_Uc#KqC*Mk%<%a z+RWss`n>J-@Kw{oL)5L?!U4C1gEJRvQzvXy%(WhCf7OGb} z4X*lNU)57~a=;q8YX9UMLRAnwu!YGvX*&f&4X!!l);u_Qu{JS*UB`C2+3Nb)Mssal z%YMBQL-y-c_7bhoi<5?7A)LfZVrV}AdFXapJLhNqH9ypg+QMX6Wh@4*IGeaV-r4kPYICMnqBkla@&6lHZu6ezFtLMDO4V3>-*2w1 zYvoVtEBGI)_5rL|2ay91D6GIe$RX6^8a3ieO-`^huy5U7Phk>(d)v~SOgUQ zo>9N?U!;D!i`(d7A)em9IQiM)<&O!mN?XAueYfcQpFSkS4?iTtk31yAk3J;Ck3A%y zk&2%dLVT7G;%8~dLVUIm;?3Bn3Jx^*H$n(0g!ly^#Lo*Meo+YVZ-o&5P6+W!LWqAa zg!pA4#Q!0L_&^Lhze6%9OZwMiNQwZ_Z6(RnE5aN?Uh_9;% z@%Ji1e0@cTzh4pJ8!AG4V?~HJ2_gQK5aOFELVTFuDx_hH@2ar&{M{8HzNaF@_f~}XpDIH95#p>6L;FctIfwe^L3bBX?@4@J!q>a;^^_2YK5CtwGdbE<|@9f z;p=nN;~V(nCcd7=*E9Hf55ArgV(66+zka47hQ!ZS#Lz46$Dawlw()fvQ0(B>2k?dD z65#wHfq)jotRSET*|3J7*bIp;!q?x%*Wba{hlCjV0?RiK2{H5lseniD_SIBjtg=0U>J3K8A*;B6x+Api?;8J_~qdX;ig!Cg%H;ch@-Hj zn4DeD>|dN@9%6oC-eNxc3|Ia2auv<=r;)4nm2=hpzu{a(!i!joxXR@YVi$*fh@FVB zh{cH6i0z00!H*Bby{y~IqQBXTRpoEeVzs}Nt!N?m8_roJ>(zs6akA|vEilY$&c>Zi z5M?r6li5ZflU_TxuSKlS3IRiAGBcjUy)2B@>3^*TzeE?j3jyUpJPBo6=~u6Toga%f zHpz!7LcBy;!;y*@IlMS2UwIj^s-JtXB1RrwoP6smFAoWcFXDVC&CqiFRx3%h#pWHn ze}960v*G0chr+%Boq9hU3;Rh8s;CIref&SFgRZ#Kcer&AAEvrLh`K*W zdt9n}_%OT{hYlY;Jh<-nJofm5==VoZ_eW57Kk9zZV~-z1-S2tq@dK*gzc7PMn;Su^ z*A5b35$4*zuLcV<*AJ`TPY5BtQT;}E@5j||7!JNy{l<<$|Nis+XonFpRuPB(+kz0| z6>&(sYI9?vA`ZPYHzX!2;?VXVY=s@@N`Uq8_X~084>l|CA}I?HpnUZizq#4#%JW-6 zvLl}fg3Ve*96dgs?xb1J8Bd!@*v;hgGU-Ki@6< z8I-&UsD}oOx0i!aT?(>ZSMud&@_e)vCUHbGzZNHwp-2JQnNr9^Cvb~cXI!u5Fq zIrrj1FKQ~FU!z_u1sV5wKHB=me!xlFHn2ZY4!g&=JLm7nvl~HkQ(lM@$taRbgg=5@ z&aJoORlhCQgX~h2W;eU7d0BP-05V^%0p>D(yUh)Kd;n~iX8DI-O4CgCzR^z!#z_q$ z!woPE2=lU9_7qURrsT!<_CxHDL9HCjJ(Iy)IT%$R9tXCoP-;qNQ1u#Lp>OoN2 zc-HBzrQ=P%n|A!D*7cj4{(6wYcC?y=t@WTACs_(149mc`sXky7`I!2R9s0Mb->?pR zv-%B-1SCB^e|I11E>6O}@rV$#;=uayS|KX07oze8A>ci%pk3^e(I%`9FwesRfh>k- z8=fQVq+xBqxJdZZo)G@AA>I>WJ9zjt*cg)c3}WxIupgG>SoTm3US;?jhOkx)y#z1y z+elh}?9&9~y#V({0QaWdfIIYRA=roYt$z*hy-E8pb_H>t2JxFeO&}g(HzhC9dzfPh zG`?{+7>7QgR^-J=l>IE2)0;t(jW-kHfPy^DqmBq;i#mn%>4n1~Ah(o_iraN)y zOMm_Q!-s@8^z+fzh7T)i1IUbAX8R8aadcuM%er&pXnAU^6|RTqXRH}_#`P7Syx`z| zvWt^r&7}Q+5Oq=cs_%dMpFH!QKln=@ANrhcKlVF6@y>r0{OP;?-4C5y{!#f|H@^HI zk1u`ApZ>sy56pi1=#6Lo`A`1N7u@`0_JPki{@aiKv*h!C_}3p^`->NTclce)XJ7b( z@JGMvKYZsmAG^35f6>S{{F_VP@z($O%`2bt#G5|x3y05q$E~kFaN`DI&cKpLaul>O2;*Az1GQ3_BgI!oD+t}VgPJn_N*pAd_aZz0+DIwiW4xT+i$ zFC%D$#MDDVR3PRK3UTN?`ykT9(0&MBc3!>;(g&6+5>*KDAr*-z=nZ)MS;)QmM*RA0 ze7#u}IErRG3b-K=PRGGsE5y-<+ku}3HCB*@5CIeQn&+N8dyVKFD@D-pL!xnfwEqzQ z!*zypVo&W81{#*5`_Ry9nnBd9ZM3&LweCi;T5C18-hT+s$?unj@w>uiJMOhW+WUn# z`sT%OGl{RlJa^&p!u9jDOV?@(trj3BWZ$*%eQx7#dqDem`SYnZj`h$$KD_@=EZBm5N}mek z2i(T12Y>L>+W5hI;~)G~8-KGqp%1u?zx{!~_v3EspDNBDbQ>RiebvVo1072jD80 z!?s%-Lc9_dD|j!CD5nA>Q44`ak3(sC97t6*()Ebh=&w-b6JpP&@&NVxhce?ARqKNx>>U8TgFC+}LiFzm zuo*glCITVkbBB)|Iecuc9XI{9+E5{YM&6Qh?~7L>{9Ktoa#$4zZg-cGrv3Xu*bY!U z{{)U$`{Z1h;DPj5mG|&QZ8D$n!|XzwpcUuorL`LyL3F;I;^C3Qb8B%D_{|LkoeZPK z@GV)`TCIgqOKxujNgx69i=N)1(ry-;?YDb!Wkj~(#`9)0ylr{fZ_8qPUcC`2d+b&LIBE>2V><8t|+uxCsDGxIZGKF7RY@nNj zQRWPA>f*|bL~~Mn zMnn$kX?O;9Z$&o+UeS!a&dR1DIHxp?Ah;bgds(2mYIwJ9&2{}G4dk+?e?2d0>W961 z1kAu?!16}s({Sdm&_++hA(RP+tt%9WB<_covb4H64z2F*!4mTbH*DB(tb5T{B@vv;N1 zV~h{QOa(kMSX%gMi7|iY?yV~9Yq6xUpC-)`HZnbcjqcFmT@dhR<4(67WWiC4@5o^Z zh8%?1!WvIw=v&sqbu}8PkxXq4Vsj|5n$M}=Zp4hj#O4fU95I`mPZG!n?q@uU9JRKzR)*P)3h83`rfo4NP-3pR4jH4Cl4SN`%QSej)XE*#P3fhp~tQ*^gQO`cV zhL!VdFU{f(Hv?(zJX9*Dlv>Be8X(nTP@Q1x+LwNk8Ng)~g;%6rI;xYj4w%yCqn6Xu zRKBSzy$-*OdL3Dv&cD1KWW5A~ID*!~H9351t{p_OdZpJ{kqudAO_|1mhP=9Whl(m( z1Sz2GhRsceakxqc7oI@<5vkf*%953pd0FfNP#61PcydjmDKzdU*~%Rmw9^2qm7-r7 zIZtnufI+K7r%a-S_NYkRDRk$^;kkrxAgcx!G(x*M$rFOSRdpxz?nEWM5l>Fgy6wuq zTh)BKQ~)HCr>}eLPI7mXgS&fL(L2pK=KWZH;^S@*IkTcvB?4V32i2v;Yw~Q|Yqw++ zV;#;CzlrS_x!;18yt*V2U>*f+xt7Eo&0;dmk}z7Ilh5g)UriUHmSV8y#?(rObpSev z> zw@5a^2m#qxDVL3}Eo~68a{JL^Y7v#_Dm1(PBWwszJ9Fc2z8-Yqtw3f;FPJYZ$ntsk z+jA@O`AAhzx|>puC!ikB9aC*z53o#f52|63zv}fuhc%!SE2alWMLIV=p2X=G*=)y> zUe1Ql3f8V}M?oSzdJQtMEnNtcG`rqoNk?q9V4fMlERECK?HY@o^GbK49v{G-_kyJ?PN0XQqTY%vbZ&NAXRlwrz(dWy%$Yj47G!~aOhB@LcGnEqkRGPQlP|o$ zQhqg#+q9g>26dzaxF*8MJM)$zr%2LCd2AeRpKvW~`dMHc6!;-mdto~Zqgs~q(yW$Z zTn$ok^Z;DF$Ezx{+0CR)O{U{;9MwMW{8%^Wc(RpdteSWU9`6M7*tFyV5q3zshelH4 zovvGj^q=lV;-^8wGYwEE!>XT#O^6&GP8dgWJCI3$MkpT1=|%ccOW8@nOs?)=54j#B zWH}j=i~eRH(_RwD;I`k)+B-7a2vZqHL9UHqPmR$Vkzp#+jd(j6Q?r{J641#*(G}z^ z*ItF=nQ^2>iz4##&U9y6_=Gv*5$+h~Vf3kkc_h(u&Cr+F&XwF$u zTu#Bh#r<2?&7wa2FJmq#O|68t4pMH(lhn@ zO0X?gw0%+WL5Z1D85mPXQsKka5*2L$!U4{o*n(zweb@>_HmT8mJ>e?cux#j!f;%h6^0US zW=T>@H3p(3>rkd z_sV%?(sz)ES?I8Kr#QVJVQ70$bCz}(UuxT7wh{NTS~F>XdSnn03fZ%&R)55jRCPEW zf2IMJfb+M*6k^?Q@qovr%zca`hf_ldk7LR#Z5l1FEz5|x&y?o4%NVgQdhb1UG)bG# zhMva3>*eH~%h56DCP9=n;5^fCfN^rNWKRyX{%V)tl({8&Tbp) z-l;6~EKgl`9L<5d`yM7IkW;H6y)o%L;40W~8n+bJ;l>GOu45li9Z5S=*R+nEDw)f% z%Fb75$(*lt<968GnXk6uD61vG`+H#$)Ve{^2@$RmrSsLcPa3zMWI<~l8`fGg?nT*r zm1kVSL6g=WLz7WF!-w%L)95mm6SIp8?g-aFp< z)^aL2UG{inezeYzyhWQn&c)ji>;ba5aP4?1uc-)M*ZA?9fA}S2 z{J8enA131mqApSQ*bCopXAG#29l7TrXz2KgAe4n0KPpLw_CEM*qUaRJxuu>C{3k8 z2DSI1r=t9!Y^aIBDhNE2J=yS>hUnzj#MG#4B_STr8JxJ?3KF>;CP6z$Q?m1%s9${Y z1JX=LD*c4WwhK>-I;)ljT|e=&Kzh0=OigsuU`*cFfF&qQ2@ntSx$SQSlct2+@Kd=O z1d(ioTVX3`ftJH4i)D){H8b5-I>+^E?{CH(kD#OW=ss|y6?;yll95z$tkk8>bNT8WD2vOnZf22 zMvdpC=O>+<$))6jGAE|p-Bka_yM5}!vv(^by-wIoR|D^kvrV>ItR@i#%#fUG5GwiP z@w(^2yAKDgGG!@PrP9eY0Bo6Y_MrU0EC5wKn5tzz9388=Q{Yr5V~S+wawl#D4Vq~3 z6sr&X%*IBpc`i=@8fD|Q({T+*%|5H;fEbIqo1WW|wc$c$?Xdy7OLrAxg_ZNmhR>Z9@3@pqIHDois%A=aj}8#KeUFlgmS`ltuhobbig z8q!4G__)?Y9?_b}!Xh%0^}4R=@wR35MI*SAj@Y>>$00tT)$1an5`R#2s2M-_n*44m z$JeY_&PiPXFIm~vy6T+%o6Z%|ny6h3IPW4A(XNvUHukL5R?RHP8BddyhI*d)csy^BBTSkb;% zv`A1-%J9i8(v$l(OjP@TGv-lh_+Ct;w9zDt!zD+nWrjUvoB|^L-D> zh@zakPWOT!J8usLUn0-K4ia7zh3Ww|CucTXi!UDAXborL3PfXcMmAvH*a%a_lxw~T zMb3Fg_e54l4s+CkYkXB888b?;M>5zB>Wg1;a|`YEIo1|UTW5nL!%6%&B77K!l3NXB zOe~o8N?D(rYMe_M$C&)Ic#6hw8%?}@GA4UOC#j(^hV^1(xb)qz8h#r&u_QA5&5>aht&Jx1;v#h_-whhiGB6MZF-e6X-?io*fk&F>iuZ~03a|L#1ZS8zMbi1(F)`{eYxfGKh0vDksof zY8FeUiZn2AJq4cTDVCnOEFAN4S;@itW2YHCw|mGE@+r_I#Q^1CC?U`O3C#uU0Bm^sgzPImDTl8HAClu;r>AB8OQ)!LAnfQ6>b7Pkn0bIJZ)eiAAXb z6z9h#3%efVS&a!~s-6~uVehI=5CT@_m2NweYe0+ifhx(e_bd;NmXBp9PGv0Y7J`Gs z$_;mzY*13;} zCmp{%rUJ}h7@Su=%2{I>e4S$%WQBp(d)GiHj(rvRCcpR3KT5tyoc!(!%tj_Bw*lA- zi_c&-{MJ314c)e2-eDP`=Vnf8Hw>+Mi*kLY!jpS56+Xi!bm!!`ILc%e_nI4w$aWY7 zM{U5hh3k6Yw|0zJLCD7PID`vHXBo6Y6>qLVMXWarh8%mR?S^o2&;}g9cj7d|jJATc zFbY~SG_mJS%zP0R#>`zzfB6Lzg_nA3YvFB4F~<5WrA=Gvb<(F1WW1wgtL>5dazj8V zYTg!5OKo~7Qef!<7~Z*HwYRP``#D?Z8jgPRJC4CWre$@p5*v%z1m08_L_-i@!&TeP z)vX{&!WNEh8M37P)JQ)#ICz16u4Wqu&*b$^4#OWiDk*8pC<#wE{Suk>x`^H$kxf6s zO!ZQj;#0XDwAp^$rIC4rsKh3G#)vDkF_jl2kVL7u|3~VPj1AUL3F7ly;D=O^;0KKO-)YE zEi7D|dbTyOvG(-!$;A`hiwo=Lo;vaQTN_t{>37ebjCSJgwmU}M)Y%O`Lrb-ZdVT7| z)WlSMwtiv?gYc$jrl;#u)6+AkcTC<);n)d@$be8i0raSAO*oNu;-1{_aiAquf&@elBO%T%Wio7~au^g!{ov1| zBLFr|=tw5*w9+wo5m2PkZ@1%ZG(~mE;=`VjRHk94*UtPXhYcPQ z2SreHib&*VGZT~3)2Aj+)lc$+iTbINvnNiSnj~i|ma$`~Ix{&teRAgH)HGqEyni(e zZ`g0QM+j*}tO826)C(JNCwL)VTML^3)vyh_LAH=5q#LVok*HvB^?aZ^2KGk0zTUR9 z& zx=5FFj&EqQ{*17@HEkI^-rC5WL2|2J@Y`*KI@`K_HyjJQ;o8nvoUBv5BZrS2(>pwM zJZwx}i_A)>Db39eM>Fua?KAibn%^Y!~yg>b{vD8Iu%X7N=asf)K7rf6EWsL@U^jHIu;4f>eQykPHMk zjQeX@fEXLHat?>={2kOrK-3TvePGsa|RYQ5I%cv-23>_UT|eogf?QM7`!1Q*}UAlwysg zAZncnBR?^kUA{%UKhL=*3etta!h5U#hUaE>M|GS2gjhN_ujE&bN%bt#C_FblU3 zMzn?v78y%Ios_u`aFloJ)1)$zi@nh+r>o0hGl#w5RlIIzXj%~_!xy%Qnoi8 z`KNS(vW#l|;HqPBH!gA)Py0zqz}|hJg_`WVGs)O+WTlW=g$J*9Zwh~iY*8B>6VInT zfErt_;cN6mmjKpRg zYXw`h4mV^~{RDmG&(pSot?Qh*L={tip=8N)?S}IK2YQsH<@(JlbhO7F=;=p4sCif9 zD{|M^SAXV^k5i9~Lc&oWzyt8Q9k#L!+3}OjAd$DUdO%sM91a2;`I+X2ZQ z>;`v~`NOWuY?smt`1S^tS{=dwa~Z!ss?YAiaI9>;Gxd5W)kea{xy8JN?RS4$hZH{E zXE+4SyJo|E|MF|dY&g02Rb)0ql1P{h_q*|hM{@QV7!C7JU^0B}xAzulsJIqzK)5K1 zR^Ah1F*Lle$1uUk2{dLR3H!qYN399k1X!KF9cEXbGHZ|WH!wtGB`-u~nN2C3_PgGT z-W{*X>JsjJKyl(FWv*EZZ{wUbJ%anRsvclQxkK%}J7&0QExdgXa_~jZCXy`h2n=n5 zLey+0T!JIi%u|vXeE@rxFL(@ZksUvkt|;Xo0tPkGn3h2qd8;j^7D~jHR`C^IHG>cf zI>(&C*zWAeEvKo3Gjd|;RL2QPFlNQsajzi4^8g{dV3TJ!CLeku@b#ghT+^Fud z?#}iSjV04*t^sw>fd_cZ?zM6@@VsjQF_sn?C58_Nw|(|#=bdZPP}YzEZ?(b0dCj|R zCxw<`Pd0=)1zm&Yjo5j?I~Q|{3)W9<#|R@>i;Sd#wok`>WrUQru3y&TfyvTlr?GDq z!zeuGXTgoI6D(zZ2k{Fae6_=t40$RY13Kw}&fnUgZX3NEuamu9wRMi7r|Ik{3>C^l zV2fW$$+w`MJHR2y|o&8$o#D5V!zo-k|0tJ9ZSr%7hX1UQ4P6~*wgW%Hwht%YiqF;h zssTB>;Uni)kX#SCZNG`p_Ptu{wX?9>b|F0Aqx+uTiDgKRFcfiA+7Xw$!-;BcBljmZWDQ+h1^HGzDo2qLlGh0f%6{K+%mhonsnchJK#c`45~}-&+OccLJX-u?N8&By`Ke3J5lDl zY*g?BI~`i}2l8S)aK~WZEr#nHN95F0QtU>Yr}^vZxUD`E=+wA?oTHchWIZ6GP4NxP z9SiG0lr3d06*z_~5`*9cr>gT>pIR$_3tXwFO-%+yIyfT0VU`HK>FjCWg~mR-o+CUG zhsC6t`DM}u^{~}6Olg5du1u8+4Qi8(qjJ_{`>?2}*f)hWLCUIbKzXREb!3L9s%}-p zJpVPKl3p@kXL%XXZW+51R)^Wf83oSYy3gFs^ z8wuBrIS#_w&+h0^Xi<1oNf?K#T(x%EQ)5zHlme-`QI(YeM>mBdS32dC0~%`v*EZLs z*Nas62@Ep>@Ic}LHhb8k6+#eC#*uEtDI#we@|SEYz1@eLYJ&=<&gJ;*${vT{es8#1r;$(x)>ku+Ct zM9Uyflynz3o(EWY3F^(uf=nfg2*lbwH>p-_Z{C$c=4`jlyWox7e-BDD*^Z2OD7O^c zJ9c=|R6pLlyp>-O_=<{q!wxrTVRl4x8%vRW)a2PR0^?p$?@d+Ri5ji?64covVViwANf%=`{VZ=d52d|$%({NSYWQb+G({s-XjMi#8>GD zm_Gw7*#jIqLGe|=R8V}a*!IG9A9k*x}eXkT-40`Pt z6LLW0^;c(Ld1Hp+kbJNCBBk$2>%s8p*gTw09b1vox%4q7?FBbNrOj@2NM}VZYIVT= z7s>N&QCI%xvan0LaLD1RuBcAxw&<{sR$kffC02AzCm3|fRfq|MYhTXbDc(GgPb?333$IM8=5b^Fu_r7#g? zp=nQ7md+D}z% zQ4#*iyi)Y??P+GFrHEYDh2@Int|{kCz78t^P`a7IEbAiVxwmEPOb#eur%D$3o{UpUb2;bPAW9Bx zS&p!YRoOBMSz4Qp^JkW6R5KG$K6NN;nXiA=aFfhfp%f;UQMA|gT^8=^qmMLzL#|;EQCKW={|t#9 zWBCY&tBNmiHB}p7@_V38fS{^@NIa@Xs3>dBB1HYt*7-hCu@VNOrkpQsgP&gTRBJ`( zEGxUTrx!TA?>FnEdSGyF=e!_7fHUR$3_$+QCcnf2Qr=zxKgbCgBW#BS9VAS_T);>1 zy(p$5p_r2@w#V9bkJ={>3PrXYe(Z{t>AFJ=9Rwq#OMSJia}Y7Hz^ghkdArKr>T zSzZ|CSZHHdVavSMeL9%q0=HK~-I8-j)WW5p?I2puHX65NRTsp|jPGunkSlVsE>|dY zwc#zCIeYH>g^N#KdiPV87q48s_PN)WZrptOnfH9&=liS8R5 zZEfG)`9OVQa%y_!#K}{$oO6fqq6|?^SRH(Q7?bnJ4u!X$Dprob1L*b&JJp=y_hmJN z(XWDN;Sbioi`KTB%1aux3DQHzUl{ery}mDAbt9EI;?!pFA>e65Xu#@CD!3Q5DG(KJ zl?}r&4{C}T#{1f7uj?Zogebouy|Crd$*%3^QX!3ntwu?UD{2$Q`$}B^5|MM6wd3^= z`VobsDhnxg0f^@-Y!;*@d`zWvvD%r`p$f(&%idR&Ai>SASIw2-3#Nc5yYa{u(AG~y zESDnW=BcXeJ4`^Au_nvmx_rW+@k!=atArb8vJEw{FYU6C*XR4k!(CpAT0xX4Rak>) z^!RH@fWzMX6m3e-B)p-?kj_f{h%@s z&fYF3mHee#UR4G7nDlC=S#Kji*-^y&!{fiP(+#fTavV+3Ri2pK=HhY?0UV{Kl$B5j z#ERx3l!;VURWAxy)i${Y)f;5P!=aI!A;hrwQ^C$CBRY&4s(U+E%8;OLYs5mu*EjaB z6SUIg0fawHR-X!X3@V>MCO55CS`~*8P$YVWO3%U*Gz;1rM`$h>P6}gAvm`g-dl^bU zvfBaHJ4}{Fv<5{RAI&V^lIn^~p6y|88GvwBC@<>u8>E!LpzEp~VpJ@sX+pK*>GW;* zXyIj2?I~5R9|Ydx!R`5}fq-_v9GVdg3<{LoEF48|N@vVl;b_R3n0BM8KB{NeDm^!L z1f%6^_K~OMsk)vO^kkNGDQZUZnUWWaev^bn`2z362pPpVFNf1bze$G*+dB)b zP8fx079|{B0Jk}b3Y!3Ra24VQy@V%K_>_XWLE`pkpNOrA8=Hcr*IByZ&$Dxs^flW z#`_JP#iLx*c@7|sV{yjXe`gb5HDJ+=3;Jd_wdxLt$G~ZYj*n{~K{J~AH=}qvg1Hqp z%B}ioV6n<4mto_+8t-O&N4-L)IH6< z(%IY+PUO8?B*$6CO3ySxG2_T^kfS5@5)@K(JFtQO2#N0xFY{NMI(}ne+3msdD=%GB>0(+cJwqBK2z6J}!354?)X)i$ zts4?Y0^g#cz%9r#Q$sG-xYh6|MCI<}N*&*YhjbhkeK^8yrYykDiVOA^xJRMnu%^iS z#f+yzddOwMJ={l|81R^y-V1jZtYaL3kN)=h8**UL160*kc*Ce#&r=i^$&r&20#u}@rA(Rk^7b<|6UeBm z@1MVg$Y8io5a~swC+WI+qcNY4T1;2;vOrf?dL4dAL^rJ`kNYtoYi*b3~6d0XkD|#A@ zTa(7EcDDo!T2;j9Oto&0iqxG#jw`)v^0W%oH*-iw8D={U&L{F{#kmL)Q2oXtg}X(* zAkdW;X5N&NXOs2iINUzgM-FqZHIws0o+!>7=t_X{RDe~$J>s5f%nysYHlsK4QNde& z%oI|ZO(7-exAI5q^@etWh)iRO(sjw_dGT({o|vb!GL6}j^LjJYn4OyEm8>y4p%)$9 z+OW4gapo5JGpVK8>FNYzNQWNLPZX$kDCWW?@5}Kznd3A@C80-p?@+q^X=G1;RAZ}~ zno(9yc*q7-FUn!>y~CU_S+08d>l+APrgB4iR7IP8ku+6lGMD3Z z##OPyhV-Zdw~o@mcB=z$Jax$q^@9hj$5B6;1L>XF%3hAw=ULzzm_7AU$&37eV29xm zQHT^%XKtSk+Y>CId4jVjDZ_hicU8J&Hw4RE0l$;FAjPt2fst>fI6*mxl@;MTo#`F@ zE-a}kY2lJ9S$Y6esW}Q1my4_FnR6gTGb}J}Jsob8rd&&cptjL!)#&m@xgy^oPfeXV zb)tSM??~P4HkM}6uIWp=jFIKus?+rTne$N6m6SRNi$wzClb0@saGVv4 zO)LZ8z7o6SwjOQ;k#67G{;g5R6+@sdebLRXbK+=apN{)+_Ix{zrotCqunuOJnq0v9 zZs^gM>y+P(qm-@!1>W^$9Lv!9Rvg3g7RxGVPT9@ei7j;JT#SJXDfR-Md^e5!ofwt? zNOls{Is$_8gE~zdS4)$TMPt%CPC2toVnb`GQqZ~va4 z$luzGJ6&81J1XgxbKILt6k$LF;oAw-8GVpUj?cN~wP&OT};X~qKsWg?|H_FeBa=&qszi87urAzGi zPf|qdjy+AA;;F+vva_N($G2Bv*}+hY>(pA@i=4;`jY=z^8N(%}qTD!lo1qGm^FLJ;>v&wLo(QZ&!um0%m&ZuW&K zM~c)zoFoWyO1Be5p5uVhGi0Dhbz5b5FjRlCD61$J_4r(OJT^YDkgBYvgR7Qo0krix z*J__entQ8Ktl4gCXj`saUKl9s^=~qBb+qoJ&k5vS7886SiBK8e4p%emsz{TUucnb9|ha`A}O}vFdQ}xqtLIpu2E;qj<=&AF@LG# zxL!VEG0wSRouGR~EvwQjDRqtTLNmq;-FMdW4Bhpi_eXsU%(bou$mh;=9ci!L@5Qe@L4=D%_7>+PPM??IadZs8EcFw=w|ZCg+eJX5Y#eYOSlmm@oJ7NYM=8*Dp4QQUn7G2064?f}`;)&3wKc6j$a zv$J`)_wDmuVy=uL>FWA}81{UUz#^@#s2nk2ePr2@HcH(xrKJ*en#8dhGo`=iy*E$l zZqju_8r-5XQs()XR1DQ4lU|_~r@WKZe$i_#-ee1(VlYR$R`j++Sv{@~n@ zxE-X6m)r)?Zc^2ZnCv2j!D9Mrr#-&ZNS_}ZJTgZJT*5s_5CVG`%qVVpLXa}$SJrD4 zf7BM+cvkRHQ0sXyvP0dQ=(>A(eE2AG)P-R-*D|MeIzPEYOe0o8?jM(1JGtb&9AB zt=gpwmIu@>R$w!>;#|3O=*$+OBJFj^(7uNm<9$z%j!Gg8T#f43^az)4 z;N+wkRy!EBym6LMIbEObTTe^RtKef;OQWzvP6CSs&1pADnX~%PRcaV@tJmr5jN$BK zj4Py6MgU4e^3H-ZET~<|a;YG5@UiznnZ;|@Menb4SVV}9LHHLX<&^xj^j5<2Q4l|4na6S2ifj5ak{qas^zGX z{jJL;&YF59R^aw6ssn{q9`d_F$h%I44fY#m_h!;w%Ry}Di@D8?rJ*U1rKi#%C~(ec zw7gW2UF?K9C}7TG&2;dn)n*1NFx}Bhxt-UY&=hDK> z2(U3w{N8c1;o~~sAd)^7usjzJBBue%hML)X=zKS^NuN^LNgroDly}TgPST-_kkPiy z_xHjiXkEX$G$`O}pfEAlw`t4#D9IB9gQ>i$R{hsIx}q^3aV_qC#TK}_B)$4r9a}l_ zunpeQS(3=fc9KFQ!^;SqjR7pu`v#Ja1?Eo>y)1?)ZoEIYn6oik)8&Q0&w5GV zB-zljcy6(4e8;w4Hf@bUTWYDo@9>$b=CYHMd%bkYe~=9 zI#~QV5e&ArdmK&kiObHPDtW0J>RV;xg?#g2GpNzk=W9HMl!ck~xSMhEafXq5B`!TE z&5e2Qm#Z#dhKTJ3D}*_0@Le~o74hxOdzZ4Dvf$`_F^U-xj<}E?YM678+x;tVQS&Q; z<^Fz^Xz=m@n$jH>wtn!{v(u`yBeggcUfM-AXL(TWu3`c>*18?Pu2BeGwcgnWtmu7! zWq5MiyBlY=-87_ExDJrE3puECW3EE%)?_*nj66Fw?7 zz;VLm%#VtxbIuxiMqfPSoC~ktkZe~F>&oORAS30b*2h7Zyb*W0rf;0G`cb*vFHbD; zd0a_s#t*M!xIT}p%Jw0Uf&^XkVVYwjjs-OrUZ}5ozdNjk-N;ghD~OB88ssHCtu2O* zpVSo(7POpbz&f1AoxbFy6*QB;PjUBR5_j@aaUc|9(nEwNLEi^y?g-DAO*1L|NXG3} zkm$a(B}WktQ%PTQ%02v!5@_6k>p%uuAIUKJ7B3>;zAzE@CNC<%+89^69Iv0{i_++o zyHw>0lr2}Pbf07|R_x~i>Z@>{Ha(;db~QK)KZd5>6fuv@Uk9kab zkz+$t(*doOcWU?2T1xk=Icv~Sn^u5XD2GcsTV^&&G3vxDX$QN*0E$E?FBk%vY^yq< zWZv{@bS`z3n{nEsO#?{nv|aQs=@fVT$vO4#(SuStSJgD4EF=AC#Q0-T>ue-#Wn64W zi#X33Gu$O&zug0u2__a!HZ)Fu%mh;@<>o1>Ar^>%Y6w1d06BSMYwt1yMSx`_V^&N4 zxI@W7Z@agP#zME-rW`aKGru68J`^gFH=yP_9n6Mgi&czhD(9F`8~ZJE_l=yv+=))? znRRfr=+Ye+bOGxL!6VWgJ|2!5-Wc)KkH-l)EdwXgtn z{2dtuK?_$ia{yNuN9ZQk^tCn?Cy5&LT>QL9U-w1Og9it)03fZF9~IZ_SIIqr?W9I?k8 z2-VQMmLN+Ntd+4zsXR!Y*{jOo*EA6A|x6WUl(g@ zzHpO@-18(|3AR(BLY5|ct9n#8K%&Bql+xTsGD@})M(s-@N$53B#nYmt)t2+O!|ZCr z_y5YO^B0Ua&>(Z?==%ai%>t;E9KYQTN)wqVHK`aosx4K#FLI*na%a@ptf8ZjhdrD| ztI+l=P=yH>D>6Z z-$Cxeu`Rz9r(;QPd|r0^FdCnlo|qk<3WAB*lc(w<#BcTtAldA-x}b*5$sWmoY?BBv z-zsiZ1+V#879^2lEyx9HL!aO*>BbbzO;>eAo!>J=%nP8QJ2Zw5U>k_uEy|T9%PbgJ*M`U!nJF@wU4~Qv%VZ zY-S&g`Wrg7YR>r6Zgjd6l+_8DMcyta>UA`aW=l#=%Hb+i7)L>;1Oa!W)18#3fwOuZ zAyjD+>x}|rOjgf?k=+JqqB8}(F-HjLWlar+0MK}(K39knNPD1{E3#HBU=kWzoeHXT z9v(Gfnz@{?w+B*6#g^T~6v%$?u@EALJ}#`~vj!-##>p1+!E?zZ;7nzos38yBrMW++q;iGHucvLlm3)2iCgLJEw-vO8V}LpaIvhgFv5rbL<+04pmLl~n|?RA5GU7z_4Bv)%*DKM zXY$qyY2QG1JqgAO6NnLBj`xn;T3N0RkG$~qC*Jw|o#kb%+BmkCzXZXcJn{sC;%X(I zu}Tu7AS|8qLj0xWGQHO9sriyO4GGIio?bQKId-AC=WmA@U*=X2n|N{cDTg8pa+5L< zD19MMv5Ze{)Tv+05LZ+k6y4^}WfAczP!N~sw^MxyH%mFY7g9!Of(vwP+b6t0rVZB|WQX{mss-*b2MQ$;S!gGEWfaR7lzvCug)|UNdJ2v@a)m&`h zvUPb2rw{N;D;WAM@iD!{uj1QQytd|C)9ckor$=W-PmZ1%ov7;@M0Hb(i#%0ljT zxJpgbPEU^5-%}%nZm1%4L(1pkqIpjwz)ihKsgcLW@DI1q8=B=05p*BCCr2kHMkhw6 zMyE$l7wPRJ>ZE@F2xA3HlcJA>e>JJT^yoQ_s&@H|dC6=#YSpM27-NR(BVa#Dk*NUqcA zD>Wsh$#ttrr8pI9h>6-dA>}F4mJ({ix2hN?81)tihyHK1`2Q!L5Y&p~G*i=|=Q|qBapZuH^p7LZkvW}_E#Y<=|adbVV z6!eXAY8qJg3TFLIPY0b_Gr%eaESXHLW~ll(^ThSexzJI@6}g59EvkmYteT<5kESjL z`Am~J9l>e5a*%>Q7O;fq~EK5!jd|T}-nUiRp7870V&FwC}O8 zF%^*2iUSVG3T}rfMU9({3)qD>TyE>N)9NN7$}*}!R|}o(OsP6J3VTi$QYwl@C}}C$ zJ0?w2u>Ttvm?W60a_&~1@Y5>6hP;5H63Qaza)iY?d!D>>n?#3uAu{w<3eQ~$i~t%$UyGY1@(D}!F2ZT> z(vDFT#TH4x-GzJUCWyt<;^vJ`cP%vxV6=$h3ZWO58=dY2O1jz#(@l3pP1|wS$fz+G z;?++j)z$i9Om!D{MVZJc+o}+^Op60|X2J@w2!VrhwOl{BaXOOwm4OLyKqK{6+d*qo z29dwoE*|^j4(U}Oxlh6;J~X?eD(7d|d1uMnc7HYrdK}> zY&pO;&LAR>T?IzcB+a5urYoU$8-+}fXqiTQ`w z%td$3^S;ZFOL#~(rqOEk1%q?_%IJX1X;5Gl0~M85daM*3T3zV@(vZ3oQ{JwfMQ6cZ z^f&3moR)cNnL)ETag7JX)xH!M4lV?L&{;mya1OvyQ0)5exB1#KTK*k!Dj%2TJmn97 zJ+;aM)NT7sM)(RHkD|w_w(&uO*EF77yE2zU z$5t`VDM3X7AcnS+W{k*6(J9go;YCjdOM@4sH$JXJAB~hByZ8KP;^Q|cF1>M2t~eVk zgBK-NNvh_W)sQ;kcLII*EeQJZ1?NQC61%_u(1Hy40n07$YA4E~GlUFCe zR`n6ofD~XlEN=|PHcb`^N&T&zmi5$a?U>AP3Bz`rY^D?s33LR0gizfcvW>LEEJ*ye zj3b@Yov+N^2+|;RxuVdQB9t7ZYfF_HOb(MJC#cLUvOwdr#pdQ|g#@Nf_0Bjlp3kcW zxnw&AHv_U>>Bh87>No4?b9)*FJ*x@|7KQG$$SjcPY;+zYJfB)%)5%%fL(ep$lQumS z?3hcG37;w@qUlZ}%DSmp(wd51gB*{xoY@oMrY|E3OnG=aOWQC=F%2+e{Y`)X%Am+c z`j{SbEn{l=POgSW%*uKmVUhd8Q^FnXZ`|^v2K859(~eOBvCKe>1LL*R0Aobm0;U!s z8|Ge8mMkL2rPr|n>?lyCAc5mASjHv%)K67nNQX3RM?;Xb1{s7|L%I-rDVE z*Kcn6>%llj64NeTofZvRHGM9oaP*r=kC2Z|2^JQ2Pcm@FNjKlXMcOYlS)eJJKxX*{ zJl%Aul&4QMdD7$Kv+Ry_J+^A!V51+8%V9s0h?mY}+6|frsy4@?{C1e_j0`wsYY~T( z`clPQGkWZSYsFN9W<*UCP~)&fZi2K}QpCU^j|k6H%BcDVQ73%Nvt0W3|C} z&6BWVDznO=v4ZxZ=GDy-WX(tKR!Wu+zL1^-3hGzF}t<2o5m85ysHcl4WP#mTijb+?!(=lj}YEea) zCSiQU=ENkl>@popf_8}m{v3YhbE}u*=4O$bRYDre&!qgi3=MPbqOa2Im3xd$;MHUu z?7Yx6%hG+UZ5Gz6Nh?tH=K@j-WfZ-~8FFu_`BMxAK~gMjR5-?3zHNO78OS04YNu6q z>hS%*Zg#6#=#ts~-SO&Kx}8Z&SfjP6S?L$Dc9&}ucx{g56=(c?@oLU?PH7xWK47iK z@yHpB8)0)Z$nFCYHMs@!D)FEi=Vn>tJBbmvPYCMWux9aMRcEcts}_`9BRBOl>D)1r z0pb2D#Of*rRsR`gp#lW7i`VE7nGet5~5^tthba8Me*c zwpfGp%X-QLs_KH(>=sWgVST|=3Z*bmnNVqF-O}Cag3jNCP^^~Paj7=QSCfx(v3n(T z7@#P#7}ly;u60{`gXT)C!Ew`9GazA#Q~XgFIeG4O2ZCvX7c~pVX(Uf80np`(QdBL* zNgy*)08*K4_>qQ3!K^Zz>7IbSQRI*dGWeh!%(2C$u%bDtlTm06=~ zcNC)_l~a)MNd`v)l_!*>hWJ%Q^+2k+a#7R06lFoOV+2+M5&8# zBT8z~LwbFhb6=b7KSg=x^ol-kh^C1CayPu*(kxw^_;(DLcX#3q{}E6Qd^H|`92N{}Q@?YNuef0^1HnR@yQg^IIQBxnxz(%>a|9u-dV+b}if2_$z16}`nLAWKz+PIm z+~YX$l}zd9>ooHd#M^g>y}(v+)N~KQ7VJuvX5L|lYD9W;W*J+qmW+Fu-1a$BA&zz+ zXr2!cf+_7)eR_mihH1}m@wOLIX-h&v%n}tuE%%%?-wspldyGr!;v`%TqeitpFVo)Y z`+{cHs7}nwPLQVldeEp&&dYWfZ8oY?^D+(FbnD2pBr`gD-gT$v_jX*G2)Z8sia3}a)hjg zrEt_vFMDKWa?4|uml17}tE1V{%rYI)KeKZ)3X#EsLf?vL@%5=LIt61a*$Ok-V@56O zhq?Gw{gC@g&)?1xpG&iJRL|wGTB1FF)o=Dvui-6Us4vf6SY9}}yr2%*N?3pVq*J3q zASiNva{1JSmrtE6yzX_KmnY22rr!>tmY>+ZXQ!4=%{cFq zRt@2Kwbl5xQ|RRKsVQ4%!%woBO1K33f*A-Jn=O=6**5yhowDWHaj&JoojtXDYQnxr z;uN7)iN?h2x#d%5&FjEVvJKn&sk6(c&Y72MVG`JPv(w89c9?7JxZB;SAz;iYGP!)l z&cb@YSUNwsJiD+wYe%(#UNy9{ZmS#N`bKRlZfE{_P)oygJwLMx%L{f)bQN(Jt=EER zD`>}E7s#pQ1&bC$xFsFR5T?32HNAYs0@C)A^`I6fNTF0~hDo#SHg#cn!IBIYO@dZ` zx#{II(*|b{N)AG%muD?qLB7^-S5z&GHf!C0fMWWconAh5!8C%9H>Z)QJ*~7N(sT2GByyG(KGdX8W8cjK5m_TGbI~k-`5G2U zN6EDcb0wwt{ytArin=|YGn8H^Gw&1)Bb^PU^jyxe)N$^*IimE&6%-m7y18G@HZ#-m zlc16yYq|zp6}+$%qIV>zOKcDT0fdRW_wgVn6w}x#F9o%6ea=KLQat{V5)0xMo<*U{ z+AZ3C@J03LPvdZ?qvyDHic09Aj{TvIPG$ZgHxCSmu@0bke}=xHoBQPC1ZC*#2z4tp z^hH%@^DmTu;`_T=n4hyMvh8KzU|?6HyV)|bkjIV=q#@j-9A$1 zd$in40~iShY@ApPp6!!9^X$r=_d&)eo^4(&8FX+`fyD>G$4_!Ipe}CGLC>PN-z)SQ z0uHx;%@NQ(qjF~1#ck5KK7zI%m>=~-3v6V7w?J+z$R>=9wx{3xp>_*Z$MW_oHe1j# zWgcb<=JBo}i*i^zIkp4C`g>I5*c)umjGc=XFo>Ct{o#j-ip>$73q>Kp59_3|f!DhV zzwDa}H``kC%`Llc-gD_?t$Q!O;>vyDtFAuytZS~l>E@enx%IX?@4EXQ?yJohr&7w% z?$lZ??TElB<)s}%_|ertKRW407yam_AN%P?5B=z+A7U57e=V1G_0i}3^n;e(H9&t2 z;zu`q*i9dHvxl?+-BFrE?0Kx%{j^~{G*1uB(?j$0&^)~~$pM<=08Mg$COHrl$np&N zs?%ZRhsMI-1&*j3?zN7SUw*p4GXV{#W?-P^fc$_Zr4#@OOUX|cDy#ksk=i$soo-vO(pjU}671H#v(2sbU4}^p=xmSCS zk343ddt`alWMVxm>kn^JKu`FqK^<aK9*|`ZZ3E7NY#xvpdjm?mfP7bL z-R!12-b+epY=j|@EN9DF_H<|vQnKI{H9A9}mgZrH!L=z>a>bPjFyw8VMfDA`=%}~V z0TT%@%1Gc~!D78*ddDt#Ft$R@C4--!c{+*31<_#6OdADZ)DkR&Gz`n7!aC!pzc*>#?8Q0LF@#JVkn2Onem+%YTVY-#w?&XC_}L+QhAGE^x4^-z z!s0!PC&AvMX#m_}E)%eL7-|9ZUSwXw{_+~e4L56LWEm_R1uFx4!Q3QTN`;IuYZidx&nVp4{bbr_`0&lL!tchAkUr zh+Qp!V5AJKH=+)`fei;;iObVcuv)a1CBs1_hE;MyX* z)*!yNTrQ?#ZwuTx$#Z{LIZrq~XeYvJPA#~!vp6>Q+$zV`C3jjjN2f`fgz4In*&n(j6Eq9BX zc!OAc2FdFB-`k>g6b44@b6&E$NhKj_J;3RDZ&d`RwOkIPFN$v|zmyzTgj}bfiYVE+ zgL_pPhQ1>K!y%YbTySfxjNxxf>7zm&{41M6ItA!Z$nH5;CPm2yVKQ%0 z-*KLDH+`i}p2U)X``(pd#UZ7M;cj_JyL&|dgUi>V`?RU5aLA!TL1-nyL=Ow&Q_hZP z+8!1%L$nZ=hG2Uot|(F`!}yw&P89^OXto6MZ7wWyVf(!;+}D;Fqoo|yZ7hTt>~s4D{uqn_0hJ+5nY}@|LJ%ScK(E`80kdXj9m72+3QK28g?Soc zpu6ipZyyej0<;`0kpZVS_VQ`OZJIY^z)s#aenIqUS^Jqx-WdR9xDnGv_OlsALTm4A9UlP9Lyqt+9;fq)4bvI>fOQROl9 z;3t#4z;qX{e=?8r`<5I~LX~ocy|sx^+hifS0Oa4|9Rlr6?>$eIFMrbR1~G?~#&3^o zi5qUI7_`hl`%EVVL!~gFFEdSK%`CG{g!{kZhAT!2e7-u*_P;nVJ~Sz`Vy5%wPDNl)_>~6h6)Hz{be*)K6hS<3o4?F@XE#peiDPSTJVkfc^Yd8(y4G0|zO=P(%8rqJ*KO zX3nATn3~i@>@?T}q~UH(NZmsDs;y1s@)V~9y1W5%rVTwqqb$N+4q+!5v*1etd!SUg zakJjN3{sgEi-z07s5=;t?Cz_8mj<5VAPsm4!6;!*0Tuy_Z1kMAXlS}^&`h4)AMC}j zbzI|x6d9#~k(m7T< zCjOGcT_ZWsyn~XHa0PZ|YR0=RBqtxLAv+0eMi})ygC)nc@(tt!aS0*wgfv`|`%5!N zNJDDp%gh>bqT$c$3CR=ESaXb!hM&*ZkU2t{H{ks$vxGEnR*EqQY5pEkn{8QcTfR_A zx25#-e5r^VbR}j2bpvpBi)}gb;uZi!Rdz+89B+AH;wkN-K+mN+VekPg7Y-mA0g?AYW^E=|HPy5njS^2PX2gQdA-O zMqBI254$6Fn^je`Y!{27zr8v9CB?7}FhV%l@NL$dL#E5t^C7UeJb0kDZ(OsDIn#0N zr4T52a6Q4w;}1LAGFE!tu-i-vg7;-i`=Fz{dMA+DR)iK(sNa@2NZ3|T+ zj-6)B7Kzw^D2XzTd$1jVs=ZBjvNjyRud23Uw%BGC%w;R%X|OKCO~Zq}F8&ztMNZj@ z9bB#|S_K=4YP+Hri-Bdrb8NC+1mU2nHZmb7usr?_%Va;QEtgNO<76}JM_?U6>BO)* zPF5|T+Pd9*@c6)UEPFw>;YYRQ!TEP!sgfyO2M}Ly$x>>ilgPg$6RhCo>B~8ha78e(>q{YR>aetejXO-JjUrR{C zI~xd*g*i?Z3v--o(q9J|6bPC<;QOm6nbup zQfQrCG_kFE(LCk0HbSxIsl{&6i>7ER``!RlaSqe`HkeA0F$t zuK&Qu*ie3UtjoDE8}?TbJ5gSX!NhU>2X=biUlwsqhyf3^MV&3Ded?fLs|yzI4!tKR)5ubSOh z^Q{m3;*1}(Kl_1K%#6J``R?l$zg_HnqT#Q9_QfaOc>4?9^Uv?^d)b$7_(;PIk3R60 zmp=ZHy!p>p9C+QYuhpJ&`GcdM|I(}eV%I%V@{ncXe_`-y$y z8&7D3L+`eK^0xiwUjMGH-o5X7Aai-|{wx3HrjD%n(SLgJXP+FK_|91`oc$|(toE*7 zJT%aF-%H44FTC*`zkB=quWozK!*^f*s`vKJKl!_7f2=g~(Er-=*w4aI{l1BvzdYx~ z_x}CaulVtsU($KQ-4DMZXks>qiK$g5rZ*Q!_r~M1J;(Zv&t5rl)NOmgyXqU>{Kc-f z{IvLAk4!BZH}~K0^unt@Ik0eRC{*|P|G4V=ulvT{4`24lrKhdkGmDSkzG-3C*M9i- z*F5-vLwhd%!n-zHaaT+8{I`Gb(b_jXmi+Fu|8nQgCmwpF|G$z|HV&iYG`9baWOSZ9PHf!07x(%1uZ(%_EQ$T1! z@bjnj<6WBxxsR?nfblv)06cKD0shv(q>?SL?zX}oSdMi~gmkf?zq|g|A1Uqs;e1bLy7sGoI{(ep~?`Ow$WXZ>sb`ngxW@!hX!+xY#?XWy?s*#7kQUOv+B z`X9Y^)4=QQdFsl&M=$(UEc@@XXYcyJ@3*CY|F?r5nAmV`^3Vl8sIA|fnRYL)8U53L zJh$tym;CLeKRR;zS+!3-sJGqw@^k+e`RoOo?)hNs{?8tStx36I3yQ~I>^|>D-@WT6ANkL3-}Prdm|W~jU-9Q3 z9^0S&^koPBZhPHi*P9-G+Zp*cPJQp%_{E)nchBtTPoFH!Y<=SO55Mh=2VVW$kG$n) zH-Ghm{XblM&t12?Jsz|68t=L7)&F(1`Ph4!mM-|!=(ex@f1m&1PrkJM2LqRW^WGC* zy7j8tHaxcQI`j*a_d+RS6`R=9@`uiX6ekvI| z@cWkjkA3RiXW#Z`Gk5>{XRqwq^wv9mkWSqCJLmTAHeC@RgxpJh(A_yy`s&=1zufSZ zhm8lXxvVGsmCk+N`Pwhu|Gw8}UZTnNR|8n5Q zI~Hr+e)YDt-dBF~uI!gDz2o~54@=K{0Fr+Tr~0c z(Db!~?f<)Y>BU1o+yBW|KK9)=Kl7Bob zJaA^};m_&=uix_P=(Q(*ajdKVzRye?Ngkbd`_6g(j{n{MwI5}k|J{E(@Azxad&%E^ z`sv{Vv)!*a>#Hxm|K5N8r;mQ^`o?%%pL*}}pFLRr_P71pe;5WKfiqKcO8*?oPT)1 zzYRA2$^BP7`sQap`o;s_=s7Tc@%`Vv@fEjz=C5a;|I6>VuiE?Vd=|K^=PW((*?T|r z;%^>3dF($gn10d6vXB1ev#;&?$Il;oNA}Lo-*Eh%mp%JCZ~xo7KK=r8-)pwKdfUF9 zd#|0k{S!A|R`Y0k=PO?I^y4obFWq_f>tfG+Q~KNset7ARKJoxl9pgX#BvC-&xr*gxF+Ftj1_zOT(p{^iHNlRdEgC(nKA(_h

    q_J)@{6Vf|JAB(fPBhk@F-4lm4*0WmiZs`DjgTqQ2~0Bq&^^&y zRz9?A18a9c`SnnKtth|FSAI`f`G&9kP&U*7`++FG#@qfnQGUI*{7pS`**ijddihS& zU?2;SDEYs6FGu$}jlKKZA^SfqD=o2Zpr+)fkRO9%n&WG&fD7R^G+Iv(n7+uz+x+;lONcjorehnI&@?I<~v{yrEp zwu2(gz*xdug5U!!f@KI4xEbg0WX&dWvSAxJK{k_<4JS@Ek_*Vm#+n`EWMl0{aeuzFKHo zZ5<)CTgeF&vtY;|5AywEkqIO?AYi3jxCkL-*t```4ZKaec?-@uxg5BgC4lblVc&s_ z_;VPFZuT68}4@^Sd3|>yIGQ2@`+u9d~z3Me0Wk|fOc$yfjiN-0kb$}@q9Ag#S_4bjaXl?=qhcx z0z@Ekq6Styq}haNY}YBma1`7kC&wdf1mN=s8SmOc$U{gT_aX6sz*EBrr>2pR8lcWI z2&qAdaT_5G!`leiK}h3~s1 z5a_XznVxqHBqo@#r&xOUe2R>BnS?x2Lz-yLhNg=zzJ6EPlM4y99bpd$elG=3Oud2N zXHyd)u)1L(;Ae(CH`wo4`uqAh=tUO(Y@ttHxs`rCxf>orPf>mcQiBSb?yn)u4S3P} z#LVE8gfzprbZ-24>6VL=&pQ`>p96o+hCk3a+sa!7P;J5p!Sd~7J%-OtGTv2>v$B<( zfN|ow395pqp^ZHW;(i8~4$QD#EPf7#lMs^MN(+OW=fiL^Xx-279k!J_87mI2A7bC( z^)>7}P{5m@Tm~VJvhUFNZ?Q4~Ql5r{3|d~p@M1c-+`#?k;)eTbC_ zRPl569k#E#SQLJ5chM*!Rm}E*Xej0lF;K&MOHa zcd)+iBZQ>b_YfiEFw5IU2>CvH-cAVlBzxXL2-(HH1O1)P`qD)R`3QRs82WxThWiO2 zV^AOHD=89U9-wNjpCmtfOsvg2E{1F0_cpm|pePjbUkM1YUu=Ja^-Xt{X zv8h|y*{khvgcQ3lT_prjnAMx!iKLT2|9dwpDTsD9HC*$AjJ2)Gg<#>9?@w zQ@nMC^|4Rq9(bDB{@US+4qX?S7@15)hQ?zP$>?|_Hl}9oVwpE!X2@`sC&N@E9zQZUJ+zuUGx6y3 zL}Waw=ILYgoXLi)Y$Ub}Pft!Hq7y^OnQ2c8FJn0yik9Qf*#_tsn>S94j84WAY7P5& zIxr1Q=?;$8=BdeeVq`iRPYw-0;vH;Q_wm9GvRs?fSqLkVH#)nzp@K6+Ms)^-6be``@rPT(PTV!V>CGy8;{{QHt;E7+;4@Z_2BSRN`-nvHbI80N0R#Kc+$?q zqtl0@)4We2^G-a%ID?Q!Y6&oyp9ePOvtXIf4lexdc_U-$p8@Uz>f9+tJ7>+&cY|uC zbMZ(gXQtZuG#|^g16ha?&hnJNQ(c7hU&z?BsY_5Qp@$qBLGcYb{!7@~N&2?ogPZAL z08OxHq;?SUNFABNWK8WE5O`sc4x6x6R3l^jb?3jK^8xm|9FhxU(0jikI9>NDYV+um!>C7O*D3 z4TFq}hg>M)oJ~l>?@yjQc@BGn{QP!g^Xb1vLbSn+O=;aV=J00KqHSeLY1dpZ-KD11 zj4`XjJril$$QT9J)N@X2SZhU04CCL{ri|gF?XcDw!7Zp{8)IO#=4iU++WLZ#(^6nK z1g5RUtmRtT?N-UAwpuAoFBWrV8Y3IEHi5lSSW{=c$tt?0RS0WMMSac)Ypt+^;6z_d z)TS4Utxb+$FPLe=32RN7#)$>KYpUrpd!lKrLHi4IEf{wAKIPr#s@>39nX@PEP+_!A zXHQx^dkStsVtmyNiAQFPb!kZJ=#vSZgg6a)#rC9M>uqjSPLeVC71AMy0F- zm6j=HhZSsxY+_E9p=aO5)f(3LzQ(45?o5>^yoWYV(^|{+BW1|>i1abasD3O(7gid~ z9wfZ*qLEs8I5`%waRDP;y^slOcd;(7A82ERira$3nRQtrd>#U~jg`kyTahfqNLOMY zTH!Di1n=f8>J9>%*}0WK`$Ax2l&u8W0nmF~bDCQTY?NEnWp)0BH5Il}dTJ?Eg1)VT zuvJT17^hkf_r^f2^;07;6g(PfOEQ_IfHX7yG?JIBA)wC`yyPZkUL?4{jnv!-*uEOV z8M`QB?5@2efU&C~!#hcb3Kvrsw?d$eJ_^eY)VXYPDlJ6ftcAiHZo2sD% zT1dbi+tCy5>*%O*TL^?RO3|>hg5~HkaCI4ntK~Z$op-3Wv5)&{jz?5-0d>5ku_R)5`W1)U$yU02? zIWZhVRg%cel?xl&(-0a8s@itL&`5GHGB_Gdj!sggj!4dqi<;}fei9OIOpH$r#ZcuT z5=lJXfFLXIn07~?aXm2BRRK0A#Y8ErsiK$-*z$|iB-lKWpw7(~K`SCkIFlI=(>2p> zr*l?8mba1q_HGhyy9{*$_zCA29_hb^j09~Gmr1r|PPYv=J7-w-oPpdXOq{Y!h_S0` zm#C|1m$+BmB^=kX^*N)Wx?VY@A^;lh z9@O^>P#!}O@!Gh&>TnsDlWa9e9ynxWSWcI~GEg4US_S>X(m9Arile&vmadM20jo$! z?OhuO>8erQ)8%jwmIr;xw~6X#f#xaODEj;Q`@;CAD)}LBqkzR0_IKX5docMTq_yIj z3YT@y%@@P6Zzw3z)e;U`QgS!i#OMzoV{gDl6gb(i6*UUN6kPP7H6%PP!0;E>lt#XVTIu?nB@)ly()OEuL@ottWlWog5d(oY8K{%+Her2U+bb8!=kll z*t4bFKFxr$tDMhIO%_i0wqDDXIEl-fa>pdhQ4TnhrEr?t^UVk)jJ+NSFo1^g7I+ zq|1j+2YSj+P1AbLOxe)cb;h3B>I85P)3>obWm)r%fSpaycHLg`GGK3DQu@n-rF3v+ zDMNzGf@Cu~Hb!XCNGS~1X612JAhDq;kod6*5~>2JA|s~gjXJx!B{!yHXc$=e%-@iT z?Y6ZD7f-+iO*)9?$b|72L-5-efWg&DkP7{mkDCrgV;e*oF@$!TgGsA060H?MMG+!Z z6$pi1Mt?ZQKDhCe&R_?)5bFP!grgGFZqvrWBvAw?*Fkcys&0-eB3OT4xUZwHTcTJH zW}$2?WNgVLF-i?n3YLgdrYr2^m{aw*0UB-d5`(}d{TU|)KqhrbTyr}3w2!eyTO@0g zT`zE|6Xqs0oq&h+gHtnTZ&8=d+Q4GKpw@SG^^N1(p;-J7^c~(_z~A^!3KFM4v_|oWVj5>{o_~JXfipW#t|4HjQ3hydOV$Scdt7tAJ)O0A zqpAX~jR0K#wbI$?qbhL8{c{D_y4uJW-6gH4JIDU^dloghACvk`mo>@T7=OT_mfnxxOb2ddB|2zuhX9HQI-j4SQCNUv zWfls52+693fc21&mYUm3j@|BLb=zn!%$bGb?O8XUV{9m@-vk194j%aOe_gq~iCF%i z)GJ&57xA-Q900voq+b*^W&^&d3I{e-#lYOC;s6{(mI}7Ga%T7ipv+@wwZ-?|B?loU`v#* zwq=K_!lLWz=-=;=YF2&j&AEk@h(j*Zt)78}jRbE3jCMKd|^Z|5tGi_QpUvE__w4tgMnpIb* zvQu;Or9r%b0i^{5Z|u01!2ayhbS_Bv02p9~(CT&_v&C4WV1_NpmZUwDAgK9TV9f>3(Q&ZfUS$!{A{wlQ`V8|?(h0UnB^4Ya+ zKr>gbqT|0bs_%qPq3@K8!73CTa?lhGLG4jhDAZUL3cXc5Y|6kT8&(kl+Ex@8t}a-~ zk^}5}-gs7+PrV{A$ku}j^>CctgT$`R2A)F4pr{O`411qOt^CbY&hX$B>PQT`t+mNa zgUzKdwzT!dHY$%pLqG{(6kHSw0#q8VkuRc+S9@M}T*Fq=0PdT4ICzDHgJc@YS#wrf zu`tKEnpWjyWwi<<3ewVgax?5KM?_DmikQe(R#?bsOrgQ79{eT`;&-dEI8aF=yX!^L zK$VP4%&3v(DU*8oK!c2bgz^WbC#Z5Um(Q_}l_#}*PR_GKK zzht`jETBjfOsPU7nqGTK^<&=Cn@;0kDu6Y!3Yn4#JzfWV-$J;mPUb%+ydM5%px|P9Y-m zx!%mf(V^&cBoUiLR*+ZO%T+zR%JaRsrlTXVc%nQXcU3`~ux&h#G_&C4bFYz2ww0cD zGAZblXc(MI4@Bb8B%D)6C#dHQ8;dAwm~?Q+qqG%b@7tlIvv|d#q^U?^6o`ly6K2KK zby7n+F{0y<8=$#^Gt<-2i9~Wbdi_i^p74xlAIsa&)j|Jx8V?1qT3mjqsAz5*ISix@_I)l&0ftS_Fu@vRNxO;m<`%xWu}(_1 z-{;oA-nZF~Uuvh#U^`lnvaOX*Awvq-co>jyl$S|@@u5}G4}ymThaOBV0b$u>DgsnU zNS8g|ot28jvSbUqHLNilU>mP!l1K>)72+l@j*&@NadWPa$QswhCnt^=sf0Ce6!v#@?*}Ary6#9KNj+d- z^hBu=y=zdA6!KOhM8QOvODJKt@}}TpuhjLi%@pecz58lNe-PH6EA)%|&0Nkb0NG$y zJuR#X*Ed&%>rbnyo~llhh4qvwSYab?poS@qk(&)=>9LGe$e9IpO%3acVJi@ieXEG^ z%E_jGJjy{Ii&_r#RWkD7t)v71k5yBX7hft(VFf7Z?&#=Sg(FX(As(j^q{6TuQwdCE zr^mZFE-f?008|0Sa_xhwn{E&3es!(&O2wrjS~IVM+);}*xqwX&3>?Ju6#PGL=Jj08 zN{8s_Lz`o@O-xQj5n{%Ml2g;svB?PaK}lnCZFh-VW78Al9aBdWqmvUe69Y5D!_jGq zax$?BNItV=uTOK3?kB#Tq7Zxr=zgvVLZOS~7AacXuBR0aQ#P(DEZR~P7X3g~__RX& z=1^WQ=-^Rba9f+G98T4~;Dw%^of9fw)U!x$wwvg{+`^b4O{2fXPd%M>!s3^v*^Bv1 zSi6Ef0dGkRF)j1cGfX)D1=%EJ{zTB!(k2srKB7Dt-kETNSj(@IHrg|%V3l@Gp@wcp>-(J3dp3|(1Ca=d3v zHWSn{Q;a3OTs6!mNIZApB2@77yrZ4X9fiX{{#>pafa5CG8ZArH{Od>_sh2Z<0hC<{ zq5HeK!}v$2k6OV~HHnwSCX0q`S{Z0*XOBaR2+$@mr4fEeT;A@ZasZ9y0BH734*>I- zK}04rNVh%HL7(&yyw?; zb{#++TxYmve|Hy8c@5l(l-Cc^+n=GbEkY3W)yNfDXM-~zoKMRVd%F+xL*B;e=uj-~ z&nUOWIy|cte7e+Z$xe9L_Dz{o60Ckfk0`R8A^4_t=2{@wd_FqM+N@*yu~@Gh@X6)m zfI0&GFVp#4D0g7qhj3?aNY53`0v@o}W>VJ%WmJxh*`)DLW%uUY0X5Lp` z>ryJ-fDfzM^|w~F>%U*sES;(Z0++Yi;6*fVGIP~*3AhFfm!ZKa%dBPRwN%N>(Q|9p z(DTBFh>cW5IfT6rFm=zQmXkPq4()Uiu`N-)0)+PBj&G zCbkwT`>Qu;yt3swE8z$_vLb|uelZY&Ov^)-$e|($WaE8Z3#by62*`mNf}x3~EgyR} zGyHS;v#IWm&hFC{|5$}m@Z$gmEu?L)SbX#)5Z2^zpCO~Z>Qps=x^twHfVWoGK$riJ_3IuEpA z@TIMuHa{zdUBz;SIe zRRRNKS`=cqZQ8)zJ~gKb(##A_;Z3lBSHF+L5{; zDA_8rl&=s2AI9*GXflUdq2g>Uztj=r8bWWlEZCTXVxC)Z`{>ZKAz7L2rO*=D|- zRpj%>;`LVrCfln56GH`);8W26t6F*)Y01%3X3lh%q?Hl>S;&AcN6$c!Mcp;&3$E8; zy;}wpP+`_)mV*MmSdNMF&l@m5s@O;ubvetk%+OZ=lD>}q17Z9lfTW^Xv|u%sIbUO= z(q`i7mQI(~t=$A5*TL%f`5G_Ww8C4>-#zC`sQPW;U2juH1{%EgqwgWfXq{ zErUDIgC)>ZiJa#L|><+J-@+HH7HF$v)5N zImjPM*jGdrJP`w6f$ljdLd;sZjA1*%YeICqBBF>C^)jP9sP%bT9PlE4yl1cMRA0b4|08DCM!eR^VT zXVOc*zglbTv5i@4op_BpqOlVNB_t#Bp4c>tEjb>Lf(32lDXwN^oX0gwi;IhG9*@C%DgcyVXMl_mQ$Q4En53R9b3Y7fvk6z(k6U+` zxty*ITctwA6P=oMbQur=Iz-c2pZ0`VA5F_iKgsO#wzzVbpx&%B}QieSTli$udz(2#C z7!Zs1t12MdRTYqZN@chd=bB1L7NoNs#>uzJtrK(RT-IGQ;IGERHUN_~XS8Wi-C5FH zOWafdN|~IssO5F=E-&bXw6RY!UG4Ug<7yep0EbpXyWL7jHjGwV8UN^e7*9X`(KpKo zbkvxUTTug*QLNCkR!&2py6NibqR%;YtuTo+ahcK=F^dBiuPB7YheZ_u@S+6P642uJ zkdoLUhogdi)>`L@q!+1e=4WX z8>yV0o_Df_Zu2n+J1$u3s$*Og#+_9a#=TS(>=w+7VF}qyFL>g9P8^1aj62CFFp7@xGBqhWWz8%whm z3tCpUGZ5#B9%JL#M;L{;v5TAP<{OeI>Y$KC+yL;Jw5xw_y?#~VX69hdV1hR zPrI8ghAF`YzAk0FuRSs!LmkwG4Yv5h2Am_|Orb z2Qz{qOYqQDK)CLXjsrdmMZ~bKt}Yb+y26gb6#mOAvH}=MDj|9ZPyrl{M24HDEtXj0 z7b8WW4bjI6LgW?I&x0hTOV-wFZO(LaI!0_*7c-s1OwDxV^vvYw;xTh-x-)zI(!gTw zx}(v)qrdk+_pu{GQ*$vCO-EvhvB*GjdU7)1;T<>94oKFqj)0Sc zfRxRA#&UW};0Z$tPh`{Wbn2}+m^L+WJ;-7KN#T6hpA=|_%BwsI;=nRd5Cg5|o23yE zEuDRY(uSg^XWgy}SI(&lS2|Q~t{Pkclnbw78l~6S96*j$veSkJN+3<1@@n9#%Vkj7 z{pCO>r{lFq<*1X>xiNgX#-0^hNnzg_L}{SFT2)t}bk5VQIH485uCJq`E7*`hIiK|K zT3tQ8EFxp8SpmAn(FIIqpei9oc)mH{UVdhAOnwvs&td?Sgw0+466a(nU zR)n+0@M!6a`g#Rptwonw=yh!m-rC$SG!Yj{_>HtJ+=Z(iLU{r-ZaESih{qC9e?kd~ zwSGv%*s7=r@ujsuOnS#UFE*2dY zKPB5GY_Py}tjxahV!4uvRz7bS?Q}>yxQG*06)v7z6)qlCadGA2OXhIP)OaHFyHx0L zmt94XH>T+RhbH14ms_yA5ZoAQ1oaGD&6|d($9NI|IcCkAYuKiY$3}-?Iqc+D%6Uf8 zkEA%5jDZuuETt3{3T1RBi>780EFe}!MRW~mt(>M0_K2%wLt3j!#0P=2X@TV!>S-^V z`3eBq(;e>VM(H#I*6e`E$Su<6Ak=!Fv*5V>`=$K6YA%watXyJB#S}()!)Mw5Qv^PhQSqSyO%Sa)c&e^w1g-8iib>kK)>%kIvcptiE1`$C4q~wA9_X)q= zLl6k#0*9#;!np*>ta~JQvKsg&Tx!lP?NOUr6^5Qy6^4F5m09yv0WA99GNB44AnGk4 zl512vA{4h4I15F5)ZzAXLt8MNlAbf~pa&d2t2Mz{(jl%4kMw7eM8rv{GEx9af%gIr zuEETygn8TA#*55Cm}iX2yABfYCIVMA0&IwwQs)ki57CfP^d@;0jE&+(on9riG7EAt%XI(F5$LS~yBkHj#VBxK_;4>!!} zIS0cRZiljGrpF+F9k(fglp^f0+7N#vg9e~FxP*}hEcP521xGOudAJtSQ$u+$1Cd@r zZ>`@)pSQ7{#t3L<(M<$%yoo)4unR)7u(E5vsM?F(pI8pPYY7+_ma)Ftv68;jW?HhT zyv^axw$6^WZdf2N?tum~9>&>m=WN3XcXqe!SA6M3TdRWo^Q(gW*0pe_AGC5gJ!Qd( z^@5@0b$cFS&S*vkHW40{hMy*-Wn%Ctpx34Fk*WyyJVC%&wq7hQhxL_~t}mvSTz{ZQ zIF)70nMhg`u1UooDmHbCXZ3ngD~q!=tl`4N4Tx_oD^XU(ZKbozx2>$2S!T;BEM~yB z0HJCQ5z9@3H@E?xPQJ~Gx5_@urLeLzYzOv~!ADARP+|&|RYb?B!qy5PS2?PIut+L1 zS`gOXyg@*t71YV$Q(r289s)wHvljr)u6Uc(PgM50l~%)U)&vx+#AOG#l#g0@L)^*< z7u$#nq@L;E@}A);4=?W>yH+kRui3R(-tx;`QTz>HXvC3WMFOY*qJ5oR-C_JAPV55! zgzFUOr$meGzNrSLO}HhL^{4`BoLgzm0TX;QyR>CZV{4iDyqQMF_;ujC&lH}f8)dya zh6ZF*Vjg*$z2|We8$}Q(7~jo91If|Jc*2($?j#1TzJc!yJT2dIU^H35VDy6$07R*R zbekZ27mFFr(o`%D_9tK6ToIv0pg(IoGB_HWh$hFPk?D!p#0WN8X@n3%x;r{h*Ib^% z*Cd{U#)&+)tb!wx(}$uo_&DnXgq4Mk)^&DaSoKRP#xVlF2^gb# z?uWz54oJXUc~}B29(bp38;zwCFoQhu8Vz<&lLbs3Pgc(Zf;F+E-uZ*`LTJA_C!1L? zX{cP82_9v?9-PsTY*;#9k=#+bE*{4qZ`+3klJUgkbYvu&OdOrU*z`@D{5tn@0gMd? z7A!cSp#f-slA4E4@X&9t0H);PB;mvAes5|oW-Zr} z@)=J{A498zl-9(;bC`xqzJnD_19zB)LUb4ig^dR-_wLC8F7wmeSMnrK09oxe^#8azT<#LPar>zHZZtMc*+Bo6bru zWUN>?oCxwDYxVC@tzk8bh6y;Jflw&+E6Q}x1RTo1@Q|qhxa`ArAIJ(jlA4R}HUYWH zupF8IW%#czC`$;q1_@#35tWstV%rIJXr)wq1Hr^yBE&zt@ke#NgH3{78X!`!@M_DC zpm#su?4QOn^De=rAR4Q{ebBflC=agz{b^RtRLXU&&jlg_Ocn!Trh8)l!p=OK;17YG}cUm=yyfpqTYV_9yfp(a{(b*Q^w zYgmiNhd5~~8(!I}5$~2+8X^r-3wV}J`8=Hp{?e{ho`OuOvfiLc(o{?lj;r#spsKNXsio3qmfyPxze0jko?Ui_Q1=XypnMz@EM@l2=ts%0a?nTAE$R{0Cs-xghWRJ#{fA&>ok@C0{f;dzl9pl?b9O2mFXXB3KBs` z-wR0JyR7=ad$h;vrj$ktMym)$G!kuOO7=?Pg6}v`#J}%ZZAbv7!jfFQ3^QnMq8tTj8Len`ndFWnxxTPQl||uoO}*tJ3w#W4GTV?*R~J zW)1vm051x?mbq2IX8;Nf1d1O)>NVDIMM&a(sS1oPt_qAih6^71QFS zA}mm}(LxubS$)Am9C0n%HVUrh+CV{YOBg+vVqK^xP$=d<*CFk>{L?33@Ufs0MxYR( z(2n*Ox$46rpB9v{cpv!=uzo8L*8ayHVVH_{GE;=@LbQlbzN~xUb zWQ|N5?}weS(XYCJw$?1D@Z#~~S?1ngk11-IdPs5hkyjc%#8@2o3;>rvqtXili5f@Q zq~~J%M^(6TNmVB{U8+&(s`VPfL6LE=6lOa5%-;pf$E56}hQCyrc(C=Nc8RdzTJ|^JZROub86J#_9|-x4RZAZ$rmnK&?i!=^T&5#-PU=@GU=Y z*__TogowP+*@dSfG%aWdWZDwb?Z@*=G|oSkfVVi~H*Q-XO|oc;YtmWWb`1Am$(`-X zr}ke)uU0y2*p6ux4)%d^7TQ;KJqc|hKT@E-AmO(0qw(veWf;7 zbXG1dqvhh?uCQLz(^=}zhfn-5CNBwvSj-Pl(%Jf)5n`d+%|gMVmn-j*k|L$SK576) z=cKBAN~?AU<^-PFb%<6xVWu|G(sFrvuc)|)<*RY;5bHqgU$<{@!<+- zETPaqc++z2LzAY_k)mRb@J9hR6k}E|vl`QUc&91>y`|(5V>$XG98Ny4J4-{6GM~ZUMhl4 z*Je_Di*2B7&11%Zt-m&tg2P*w4(<4OWY}4{qh$41`N<;*{m7xn(&0pW&dK#2?stx& zr4TEElQ*l4+c$V>^X=!gnG}Shftu(QT(IYF8H@~$Mw3I+vBPxN-;*(&qVA@%hP{t+ zI{TbLzUbO|F|*HEa&p#OVUEj}UMmeSh~ZWeRTTpsFVGxMtDzKbDpOS{x2*j7&W9*m$gZ8U-s^psu>ku0AMb$K(`6hwYniSq=xp!=fN8|C>P_Rz;S4om4g0+Yd*^4n>c8Mw?$pG2uHQO~Xf!63H2yNMMgiOh=}0e`^$+39p^qhAvVcjgL)^OpL(9G;rocYBcIs z4u=c|t3m}46fgPo6L^&t!%S&$ZIIGp6M2{Kr0qE<8)URli0T>eUXW1HutOL_@L;DF z3gxUt!w#i&$Dj{GaE|31?9f6X&~52y*RVs5;f5%`#}!@h8XU90md^JoSt^(i116cK z+CfGB(QQ-Dq{5wOp;((q1zy~Dfy}@e3h~9a`0w>~_`3F#S!j2%S}3ixQac&eI4uN5 zltv+A6>>}3lHq8fkZl|*nKoXyuI=$H=vG)0=gF4P!i0?^E@pbUrLPHSYrIkyHqyZi zyqj04G;Qm5Eamm%?Ri{h5FXDZ5x)G>nOs0lihkLdaTmSEVQj*?O4~T2K-p7eUJuIZ6zqly)G6A`6KWUQq^8sRq5R zs(=D7L2?m!{c;E9?&{<3gROz3XaLEjK(?x6clTn#jaqCLl zyRYa9hQ}&5?Wb$b(n#vTwuyp$JTboHLt3t;FeLU!_|&@dGCEYJ@lRK*8k6f&L5$KsW9k*{{J_WtO-;EShaS5ah2x5F zf;{hXi%y8vtzpd)5qR(^h|n;b9tm5(AtvDn?iH)OX}H+j8rD*}*fudcN9mrv1KvDb zJ}z%mVl4Qfl!D9iFg9V^WktitNWJ;0LiF&E>K~!;(*o~q4~)-qX^@GxY>whWqBOE9&1Fkfn#-3} zaB1V-Bf>IwvS<{vIE{=Rhmq0}hU2zr6P7ld)1B--_;#JXpyQV#M#{0kB?*5GlyW&I zYr5jjKiR?MwUsy}0s2arpY2oS9=b9~MQNLpKv-+_lL*~)xlmoz9MLRg5<@q&Rg=yo z>WYVdA#D7tDP5T>A%JjYlYQeDAl*SG)^^5x%j2T8Mud!RFM~QT z>}`4}WBRYtqB$AfERPIOMg=(N>jk%1_#?c{0sw)zUf>580G7dt0Iv($TH28czOK`zaC>nMI5glMHcpMep%V1HHk0D# z@>|A@jH%O$D-qQEL5*rNsT-JCMQ12v6w+44EX*Bjok=^paDZ|CdC6Dm9-)`R8nmw#jOv@a+HTjQc`bL;>Saqng%B) zhGQeip%|L9up?o~N7bVbf-o;wIfT(xKJFnH?iEcBd{^qo;PwK|nLnP#EqDu^Qe4N< zF?b{W?KM^yT+Udb7K0|2VftC}#GUsh+D#i z5kei%&QdSs#9`b$^45ZBAVa6yOKn=rg{*3Lgp{G_a8plCPaApgW(I$ZxK+??d!II~ z103(uCKn9bF${a3Hd82~v$Kt*UkAQ&@B&MAsHe1}B@Pb_;QPe*&;S;gH(VVka-U2z z858`j(DX!NZ zT2Tkr=Y%cJ_k#|dD3*n_))jz{Z$vWk%n(GbQLE(#vOzG_8rE7?4SMvbOjGLQO#4bT zGlg?m>-f$cxIk$a12$y7h!K)x7z+NF?GTW?iZeEWm!NJ?0E^bn8+b~1K#M37Li##7 zx>tK_;gd}yuF^VCaG`L?d_?IFDZK=`x9%;e-y}F`ft0gd$pWke9UFd!R4L=;wHKyK0$(c?Q1C8pk;Hxv2sQT{C5n; z(OSa&9UYx5(4SrWY6a{A{VV%a6_8z46_A}!fsA>LR}>)lh=-L4lW;a_&Sk;s8=wf| zq_W%DS*eWmqVCqNnaZ(CgClwU4y&NWy9Ervv{i(myjduZv5r|707)BJ%ImE(+!Sqs zIPX@4s1&}o)zf=q#5_qEYs&}AgM0zgS^@3)!HNa{=tX92i#%OFTved2Tw4T3d5qqZ*?E`~D>QvPP^C99t#$3Gc*crSi6g@%$(`CM!~SP&c42G_Ds*^ti_~W zunJ3gV2s4QlNz-u)nqPMX)IUKwp=T1<=|>KdV0ofLjubaXLM0IdfGUWqU&1P`1Of| zmd9=xTFSQO4O@U8PgEHId5VC8H}OtjA)H)s)(r52^+jX1D2L0&Q6zA6d(Ln{1Qw;T zpuX}!8xB2YDd+7fQB4KFgZT;LA0S}fj*te3*C`N>4Lp5)iohrP13;+Ml(Xi-%G;c! z+?dfw=gTahR`o1_km_szP|BmeORJiAKt8#KzH~b1Cltm4{R(~SbsJ_q3TJ@5BIx9$ z6MYlO=)~~k^k6g@k0uhaiII46I5rkdPDQ83V`yoP>hZclUxDA5A+qm+?9($76Vd5- zGCC0%7>lAc03_xred(@!2BgNTH>1hH$;m@8bQFfPJaEExyw{|?U}cQGT{=6nlzRHo4*%=!!Q!njwMZ9AJ{FMJAgmfRr(GAdI{pTk6>LLYEB?S;Mq{R>nA z4XX-c_g00m-%~k1dFf9@=1-WhNRID_WzWy%tVJce=2}(`<WI(-8Lb9_S0>pXFp<%Gdd76&zlZoMaD^N1K2$ub5-O+4Z0D9CMPbJAX}& z9Seq=veqjAcRK;sQ5cL>9y^L_O*m3*l zcVcF^d&#^be)x8CIyE(SY<#%?dZh0l-}xr=9ZEwOHGUpjpRh|P^qe&~IUP?YiVn=6S2|0^L;vldqouD>%C$ViRkp08PAT(D>eI+vMk0yG zKqRhCBww=L1-L`a#e-C^@~>rtCmXXzO&yzHTYCIZYzjs=c{n;98^*9ftOOngrYgws zbRb|I@Uf}y?WXs2dD`w<4?MAK`*yYMUee*=IBGCB6uW~gU!Qhg*UxuwkgN;wo$YkM&=<< zBbExLyTs|I{ zeShz<$awb1jokwST_dylP+@#Co6zW^qwZbm?7(og3rv?tK5!;gQAO z{z<5Amnb0_nTjP7lZT>sgE#9M++qz~+d)r#Gge+V3p}dKc9|EEGpN0o4=UOw6Z-&@ zA7sk3J7wDC78SqjV8@Z@!06=Up&-DKg59RmvwH%{taOw>xeT;LfQhPcI7ecCiY;(j857%i)u#p zz$+BLj9F_1UUXMafWXRx;>y-qg28;DFW=$i+`*xP8r-*aO3_-lh;CY5A8sIb8ms00 zQ)o;dM8a8p=$PdiqcFRHSG#NKF)RpGe#lc6a8-JT%d65mWH&3;YgGheLCEl1s`2~v zsO6WHF><0*kY|? z=Su5is@1xZM97t-vOTcNw1(Bz`ZOD+CG4-looivbwfeXZr@qkt05Krw5C<5yVZWJW z8&_D%twU(~^Lf3H2`?WAgAK?jfX(U#WF`4LP!;9})a3^Rg?QhnP^NL2rP&%NhCx?x}h`4GjdWBpSL$3h7?IM=F+br%&1pDXfc?N|SMhiK|RCjlW=5 zX?FGaa!^qlg85i!9p!&MFtkKf$}TGvUNX75>>U%Np)>wEx!mjp6wy{DD*IKgv_0^W zhCGrrpFHeS=LQPE&@z;f#fV4=7xlU2+!6}IN^*~&>u;|rzH!;iJGE*G9yp@> zPF6KlC0T5_x)qwJa;1vfN~vtlX$Qnu(RsC1@p#!}(bsCX{aIJ)@anp%c5*EuBhmH; zcFZRV!jzttgeitp%6?Gh>57xGSkQI|naWQo;)Rp|q4t%eM_D?TL8%l7dHvF2Kw1z2 zTf-WrPH5{WIr%Ce)bD z;Gy27?EH1v@guR(Lo4ol{*gIWr49@_ zxS@hIHyD+wp>rpqHzWqfCTE6{cy)?E3PpD1&6T;%^yl)a%(&*W=_Wm$HXJ85g?HAS zC$lA{XX1(IP;zK;JQAZu3`|AF%~QP^RyjC64K>%~d6Ne#WQ8VgrTq*wd33{q>VgJ^ z*DExuOu0d9R<|xnGmkagR&;w>TwH9=x_Noy5}M6X)e;Zx@BmdU1q64f zI|VPm|4|yHV8?V-e*=hUl`_g5QEc+6(%f88mFDK78x+k=>#UhGl*=(&D;ka{TZ%Lt zi5t1u5F9QV8IS*jbY@u0n&~XOTQD<*L){tJ&B~6EF4=}QTPmPiyMtOFXpiP(b=xe= z?L((`J!RRtYc3dg3G+Vme8^k2!ENmXd@Z92V&fX%^zckN?a7v{uNr8j-GTET0cs#N zP}tyd)=Q|({-_BG^n>w41Er%Jz-zdf$X(03Mf%xoe>$e&^Dx{pjc*48Hec?R z<#d9+sFlgOvg{`mpo$EzR&*-F+RD`j?4r=sm3Ck;0BU}waegc*((JOt zbr3I9mw_7M<9tevjgGxAmEs&v;e5Cs(yNy{RI3Sgo4i=z9DtmX}P^)w<_=L z_&Q)?XX8LkYMdG-y=1qVI@jJ)C2wzBi=W_9U7k27c_ z9I_2Hpxh>?)i$b&CbzGu<=3Y!KWPmt7T}n*$X1|j&DnZB4~MAWOKdC{1viwj%>|F7Xll<`i-nw}XQcgF z1AlZ1;Ub@RKK0=GKkdB>kR-`@9#*rjnc3If-un)?L+xM>a|=#S_q=vz8(09dGqbyc zo7c_bUI5&xuFC1Do9e3Cs_L1Y!-0ZLSs~e^MM^ShQDgu%DLx>Aq6vWpNSX#|KFo&* zG583O3|X{nMbM@lAxDUo9Heg@-=B}ldh~4X-rRz;*>^GBoB3zvpMU=O=bwN6`6s?h z7WZBDgp<@aK2#+J88i&@A7_LJ zLfmz=#PPQ432Qaq^eTj4e-6BKC0MSWGM^?vno;`4| zG%ow4ccMHL@6rb$^YtSYPpz!ZFTXN>ZSB>ZH4EJy?(}JWt!er(Nqw-c);%H{a0ZO=LN4&{f`W z%fB4HRM=Qj>)2yW@qS($Y$bbE#7u{6xju7v&1S@G=I*A~;}u=I$^^}yzeu2*f}&~@ zlA`oJX`XL1JEZKHw9@B6%PgoGSHX}d9*`)S8H&j3quWJdP1i0Xklf{ogC&-gXhHH6 z5j5dM!;0zlyi{rqBrD|A+3a8|VKsj5gPomikNzbVVtoeO=0S^xprSWoW=AY(>@eDd zodv(lERdg#xZfdXY{%7w46XtxA#;vQf=z^`^qsq!27iX{gv$Nx`wTn@Uyw0FGPWUD zqq4`E9asBV$DI#-h&pah(xujuboowQx>#;k(V}iDr&47zW>IA;a+&XV`v`Hrxj@E? z#l@xAd;w93Smf=SE1qYyEuMc-9tDa?&~bZ_E2U&97cCw4ZlWa}e~5z|m+)yWg~Q#4 zrHfdY;PEAOt4PV|5*G^yB&jo3Diw}c6i4TU5|L0!5lDrS8|9PtGfr84duHHJ4gR4O zB~J4JnMDQ-8IXeC)q7@UadG99#>~dX%IxQVI)txt9p}e}PE@7QT^y|%ym8FFnYcm`C7AFUlclwSn zx(If9ZvOhr=Hf9&PSbO3?nSIL#nU{sL3_E3e)(9oG|u*%rYd*DX=bfp;#jD}A*Rp3 z?el`*f4`<&Hj^muT|2IV3Kge0rs#`qCQzJ zqC9y)i@SqJ-RvXj0wH*UZ*o)BQ$;KhQ88f^L#KJj64=WEpZN*J&vZ=JHyNH&AnKU5 z8`&K17cS$jEQ;et2#b;nj&Hq-Zb`t-)kgs=9U;Em&((|7#&hhU?-=nAB%8 z;$ygO&Tp>CEL{$uvU?FEa(j%+51Ne7op*5qLX!)_b(1N#V3{GOKbp@72~~e);sZ<& zT>Plys(!KO$)~mfpLiE1ACvl=#* zN8WJ!xWNP2xqfRYaQGQ4#|}Y}LFSB^GGCyKR89k zZw{o^7;*I&>&#K(X<9>!!KowolUgtwKQ3mSJ7yT?ktN+V|MRZyns@hD;8=;T%)&%{ z>S0Oyf%HL+|v z==jMfa2ZW@tF~vkZ2+`b!VfKF$_^Y0aK3592{YZq+!mf7Cs!BeUv11T&MYi}R>x3P zDzlEfOAm#8=eP2cAAF~RO+|K|D$|~yDm!2Rx(e@}(x2V!)aSp=Mo2yA)ThK$ zvg)zhQr%^-2@mUFL_8Npqp%$$fjBe{SriAp)=D_;)VvO1nTFJiY77WtM} zPvgS!`1qdXcNff@!}CJfV+Y!nQ{IN`In=qs#i9*3HK!LV??7r7&)CAYW!n$xDE+uHPp9W( z&)m4q16?j`yjF6=*58V(Ez7rx2W(Fi3(6xlSx6qRok)9`zYKTG-*TEVVw(n+UZ9ed z5~M`qj1@7^~dryl5@&LqzGF9eLRYu-% zxRu^g>UWyTXE1$N;OB)+{wt?)iwj&75VgC1fUiFI#_B`5bHC3L1Y1SO?xW?t2T!LP zR)Mel2D{2pxL&q+eIPB$2dC<9ffJp2(_;+p;8pMp3DqNVz`O+$(j!_uL7cQACcI9z zoZjq3lRc^B-*Qp27o{p%HbS_dLB+A+?Pg#_PCUBb_GDawLZtAD5c5*CmkOzgm9pVF zbyG$HH_ffUb68Y2hf^Rt1X!nANJ5b{%^*zNz>n)HK`Tfqs2nA_OoE6h_l=^J zuH5%&h4hf+`$0l))5Sw|EyFa2U<4Sdo1aj?_@qVoXQ@o|IC$6<0S=ttMY>5UOL-u9K1aS3ReXlFT;@5m^fEyS z3l0gHmuG#!p0?nFJkL|jn5`J~WIJNbu6^5?g$}@`m==90T z7x__?w3-zAp*Z&V48;ix^L&?n%7%!F$uS&iMU45S6eYM_%j;k~YbC@g9Y}oc-fG00 zySF*rrO^^pQjs7(d8on|4F$U_ig2%)=5nUe9Pm&pa-G$njIV|uNhZd#)5|o6_J-=_ z_+%mZc2>CX&(MB>zs$Q3e@-q~7+Qr$YiBtI*injw$vTWMrNQ9}d9qip? zmP74o@5%5_4t^-~IxW{1+8O#WHafaB`A6~jCh8xr6mI&S$i*aSOlIe(-biH*53Lp56!I4FV4?y zm~PmJBYTAI(DGky*l^-Rq|mQ8vD#t7^3Gx}n5PJkl%HgHB{Kv+@yhj>U=VlLaNm zC#n}*#nAeYHlj5!6h;hQeNqifRg$6D-ezqpRpBP}ZF*uAHeW*tYvZA2&^|j(JsNfB zVuTBWqNd$YHyT*dxz^(PT#Ir8zrisaC6L(sr2opz`L%gbg6El6rFYS=IkP;c*S5Iu z;=DOb8qn^Q#`D9U^jFsA=GV+?uW3*@;?i!__Bsxm@t}g0s_#Rd)nufgZIHzzC8^*u zsh_0UR}m)NedvY|QNb;tAxaJKFB**^wgvMZg$qCn@LS$ z8iK7d&vv*HjHdixuX1TSL*$_(5IJc>`RYQ~-r<|Le9oJJPZP2k1$!}zw3^e&y39?? zdfqNKR)a2+qI;hqi>f$p;EzoT50`@V{=6u1-n@b5J}nO*c>GeP%WulA0=!H80@()E_PRMATnDZeL5wO)oMkoWhJa`CRS_2_N+J_i6gtww(Jon zPUw5rvwTXlVoI|(2zo*PrXMJTA)plck=WsuXSL!HddGDn3E~kPa!Bf;A6!xhKCGKp z1nS5Vla@xWZeEg$7P7WoJe|B>H^8>f{yP5TU&Lry{% z6+*gha&IL%7_JJT&W9ey4SGV?$uYY&KeI7!Zr~A3bK$zVys}}=zq+u#v7W)ed_mxV zPhz#qYj_N8gTR+J7Z*+8daIkSO}OyHal>`Y*_$(KFN|HfScD%ohjlsMwrp&t@Qt_6 zOW*g9SepgIzcS2TgQBL zZDDCByS=^jo7yZDQ;;67#1dv9IZ4d35FHE3}BWjxOj6In-AfvlljsxDDpAl$7}Yb$`?hLlA#4^C`{xgQ|^H&MxpdA(Dh z03oC3KSkX@?SA0j)@#3{+6}@arrM?{DGn-PB&X52UDszKn})${MZC3XR2{_OmPU>% zs38s`H(`}1w5irBsKvTn8K2_+jTgjS1bk2`QIN__D}W9e1}`w;Oj#1#_5XPVq| z2CkpnkwSB);l4czk{<=ZK^?B^0zB_Gq5P}uy|pZhYR*gKYt=)$ zUHoM3w|(x)i>D316nXC(s_Eyu%lIm@F*&%(B509-+19gO ziCw6P&37Gt=qice2o5_OCqdX~MV8GPA&cAq7hCv^NI0Vj%9SxnMGJmCckL=iOZHFC z1XCQ4ExGGzX4A|oD(SuOrR4c#m-o4&Y03_=#4RoCuk?C%eY(t|A`hj43{KajZ-BhS zVGdE`!j<$auT{!`51u$&U+O5>^XRGK2OO5H&$y3ZV}JBKclyP5$(0ja^DB7UzPHq` zpSm4U7?lC}kDjicO!ee@``hpA>WRRP-@7wuY+8+2lG_2o50EsaM_ z)q30sN&1@2AlWuIf+%8sVs1p(Wk&pN%O($lw!l%0N6iK7#ziZ!88fTxu{iejd5i0T zZ$;6Fxn?=^z3B39+^1P%lxPN9TMVZ!bgSHB2@@U1gOz5m#jzGNiFvhtfEzeKUt(g$ zEa`+4pwW$(W4^G*OeesdDa-RNj=uZB+9XdEZ`O#h?S4x}0F;DmlUYLaN)dPvgL7e6 zSVXT}x^k&be-663B5wkA56t$Myu~I_lkw1tK}}4nPjQwTo0c5IzvAn|<7=!JN}T;K z@8qsz@zzabHJk2(x^>fMtc%-{&yq6F8*ksLat~>zAq@PuZ~E-o%(ZI^8%r-W=9gi- zoolQvZr)f}UT<7qSfs!w1G0E}tHm&IKl`|0it8jVJi%8Me5;k^nAN@&$^i1yS2+Z} z6$Gw3$|^n~!d&B90UT@JN|N)UkuMGLD)6l!jsqf=*IGU#TEVvh=?6$xaX5nVI~a!;R$; zkqQQ(`ha%>@75jlUw)2DTzo5Wn%+_GJvuR`3}}CX|LjSIUhYYT{*oR)P}_r%59b47&piS)jXTZ$ zr)zV64m!X?q^-!^#b$gf3jCykmkaQY$QpATH!=4jH%XX}SZZsXI8`@j7`jdvEd(ux ztOQX@{LD`vswp>t4x&?+DKuT1zTE2rK5B}b$xs9f&IP%XJg5tpI)++MNA87yd}dIe zfAo+SO?Xn;--Jbz&k1$QKKCL|Nigk?iK&C{bTza>mv1Z<%BGGM?~r$tzCiL|KiFyKXGwOD3*v7JcYD$<1uUT+++`i1fR3$>{WJFU*^*RRd(FJGR0 z?ahVPg#VTIb*k*OOuSX-0nLJQ91ug_ZVyQ z>l-EyDkdg1c*I1|*iLBLo{LRC8R3MHji4gd4iYAy)T<(*4Hf;6J9gI1{83wG;-EQw zq;iu#S7+}V5J~KkZ3iw_RYxTNmlh@afdXoRiMooH8r}!1)#_I0au`%$!EpBl*)CQGU{)(L@}(1UIt;N(8_?lZTT(MrbfyGo9M-+MX}@L zB?u;Xd~IcOd2V*|+WgYY!eV3YT4Uq2RWcu)Q7E=8*TdULXi%@MygXjajWKzlnWYk{$zJy} z&yvgKBiYv1UtCx&HoGkFej<*&dbR4dt#FjxCWi&=wn4yWvh~Q=r{&~_eh4Zay>eyZ zfWqZNu#`n6ZYKp~awJ_}+E{I@&#%2aPw|qoVBP-fh=d*Ro3tgWA>*%xYwX$j^G}Duuc2)HY6Hu%-m94N{Nh{8dOeu!i zbD$DKzvcS3HT2G^mMEtuHK^W`8niW_Mf1sM&lzQCnA&Z?{Hm?$3G`IcC;gPDb1qsZ3If=-6xA1ZKMWJlH zy?6eD<|jvAcq44R^+w2AZ?)X5w?e=5mL11$y%E3V+QD15+umDy!PXZ28NXO06T2O{ z5sS@FHJjQ4)YV&^5Rs9enq`}v#>O? zDoW_OGh&%U*diw^+R|RNRU_I}S5^=uo@pxYUVL0sA+Dm5ZCX9cO>Qm+Lda$Js?=h- zsn1gINFgp{&wVP!s+Ml62I^Ia)BNBQZP;NU^PRYnMr%Ts6{v_+Rd&u$F^99uoY1tc zk|w5+uK^d%mrn`&}4RZk)(>=wrD+17Wt_pRiE0C_t zTrF3D?pl^;aplTHS3pfk5pCo(n}dr|1Cy7gI8@1=uh)f`S8&h!yS=@=Y%q7!qZ;LF zv@#Cd)z4I0LDiy?buA?b@`@OBWc)dP^NtGKZE|295nz#0a(Z)|xpu-UEx2$@)W%?U zOAXiWoNV`%QqVIyu{|(A_#GU zD`e13QP0zK9?Lt?s>UqAy=ihOMh%b48rJ7GHWrp|tT$F?Hg0Ow=vxS>;u}!$b9Tg2 zyOy`Z_Q~x!6V>yy-oDxioD~RFxCa29s8O2?{`Mb#MOJ{Ra;IfE7;E@eLV8~OgM%#o zM~pXe+kg>)uuyX=mDt*4=0wdLGb=cN^4Ko(%sneYBuS7;yy$`R0bW#m)u*-n!SRSW zZj4=YVdtWiPe%i+)za*vV(@y}5qzkp9l<}%7)F^D+1uHp1$(~|F^Y`l`mGUj+p>3X zo!o4*#NzNK2}dS<83guSwI-^;jgp;r`;6b*^{49I{E3D zzajPd1**StxL$E_JJ?|%I`IJ3kYk2?z3f;uX;Z6%voo_d=NoeiWL_HN=->equ}ILP zH3uvOmhAHIIw4x|7bu*BVA(Wt$hQZTnz zsEQ7fxr)t6Rwixb9X6b@Y!7l+wWTC7_!w`@)@tglFR*PUNiIXZ@I_Yvd}aKdY3nKK zT(hc+Z(a7vA)#52Kk>>ruc-$}x(!oS&3CjFP(A$0xkEh~i+wj_^mOL~5aYun z`k=!1^LELr`s~tc>n|-fX8-;y&maPZC+1ygYj27ANO8g_4cmJ-MBS#tLD5py>d%GB z?yL!%CvcJW(qw&S_S*Qjcskv*}xgj_NkADK6fodm?s!jgl1&0k-5RcDA&u=SPM7qg=&M@6C_ zDUF#c4{~LmMDIw89uFB@Sem&p-&kC@rnf7PG*4PdV%gg`??9bT(3v_OvTV#RU7Me4 zEX{A+T;ak=^nOb89Wva+V&0F_Z{HVEDrib0wghJ!(kK5MbF5t6>?djnk1YZ#qB7l8R-t zI7gMQ&95%Lwy{zm$535p6tIa$&oIZym*jRyU&p`I6 zy~s@0y~q&*gI=&LJ(V73i*>g?Ha0prdYQ-|l1i;o+KnJWjsLBDjUP_l2bgVdL2xWz0A*FR;kqf&;YYzDUkU(p^KP1()Z#_ajMjznchlH% zxl^c*!)yaZDe<9&TdQGMsRKW#8I|(y68ijS5P@B+7XlQEV z;%L_tUDUOYyP__E55_*HZsZt+@XuNofXh^B$a%-Yw2KNdTqhSM#X;rD29VM9 z5~KV?!aXaI_S7Q6-F+9Wg7>{Aya_ zv<#O5Shpv)scKlsahD2eT5%R#!Hr@3Ip{86dai{U)9IrfXFaK=PPVgIgX#x*qbep3 zjrH?~dus{r6-VEUx$|ya^?g=MFMO9wuimfva>{`2C-~2vX4yx3nq|MH&$4^I>dV9D z@N*yaZ`?-HFNka?ld{_k^d=cV#X(swEazcM40a?!6QE7T&q!txagF?Qv?qCqeMB zo&>?8`YEpikE9@keWR(8lG7o zH*ENAbL+yeq#{Qz4G)^Xuei6jH!5Laq(KZRr(-Ai4pt%-1~CH5?C0z_)c>w_2Fj(S zKGnI?G$}%K1*>fIy9tsSl!e;#SSm>F+5L#C5`+?QcB)LA(l`RM??Y0q+y~8|byV(& zdvFFp{+e$*IPQTAJ1eWimPhS)7lhDE#Fn1~e%wwn@EDZSdIdcRz?q%|;CE#- zp)_!mbaPqj_|S3Oz;W>;03;MkOhU$l5-%KCMwAze=o`OPP0R}IIfgSH0vM=AhZztrC_yDw>BgR4ga)b$NGhXRovh+IT6KNjx0OKR0c;?SjwvVXubJF>f$z-r3P;F&hB5GOHaP&k6~I|w zSxM}W$5_KTTN&)RV}^15A%eZtacvHab4dWde~nj+Z&Xack2!8^1 zX`%UsyXt%;(VlQt<@y~&Y^60F*ltI7n2BP`;8dd(S#5IrOY<0qj?E@Z_89ZcWG^s- z$ZW$E5CQi)crR6nNJ$nM3z_R!B5b%2aO^f$8nq{yxc=u^epk7wYA(5Ur}AV2{;nGZ zK9pjS!Y|crF3erkz4Z`J`bH*A3eVErq3qjTY(W##lXd!|Y(doe_&6d_(BEoehjmn! zvNspU1;CCY08`%9A;)Utm+SPGAj=q=gWt1)DQ&*|TWeEnaMjFDMgK$KDvddzCa8Nq zig@zgPl+Y?lkX;nVg*Pi=r;~mK}?vv?LR0V!0cxCf-bfP=w6NErwXFxN^n#O zv50RaZ?V^Xn#;|>sUwClIHe@!QOA#qStlTQk;Ov*U8AyZlO&^UKu%5MG)mk~8wiRk zHW-zYX--dabG9cX@&D14M4u&lL4?5U_aZPiXjFl*Ik&uSu9GrICN$s799nde?I3a! zD{*(3X~pIq^E`Y<%Z}UDoVDkgxso|3=#CWwJm1e7VS0RoNejgu*HRl_GRyz zA24Io=qCHhl{%$eSIL=z&{o;;<7!R`O(BH1lwvU5;ie$k=y9=7u!c`fOxNo4Co2J` zChAiYTu}LXR85`^nW)n5TV5f~C~8sR!sJ3EE^NI=Dx_(L6jiz$P<`KDWIo7EpeGMm zu0@s~Q=pUwpw{Yg?T7(yG^LI{T6KawA5X=`Rp=au?XFbL0h!m62Aka}f19xU<2xe> zxlAjKKMy>MDj=t->2^`s8|t}fR2DS+JeYLPi-DN5M8ADUC|WWidm zXUbW4XzHL|c@sCN^Nw0NKu)UNZTz~3wJWtNV|DtY#9GPLSTbY1gk?1~DyLs5ag_!D zeMU(tnuMIScvrKV<#UCBr`@hz?9boH(RneRdnb&2>p|UI)5Stx_PX(D7`3Y*f15?g zgOc;}?-$1X?=3g(!xyw*+<#AN+op@XF-%FFxIKBh$~#`40)bEPfAloB=X;vlKd#U1 z`%_tF%-E#|x%R9bh9^GoEGPDYc;G_D1*PDD>$}WL*o$s5V%`YI9KRairq(qpR+oBt z4-b9rYPKMawwvL)Z{^Kng5dllUuq=>3{01)J6*d1llzr-67qnX+%<+vC#|HA&@sy5 zkrq1IMcKH1I3uVrXmZ$dAJ1xjQ*7ax^?i_r0)ukU#Q$j?N^Ib(r%KoNxw46`o$7f( z$BjL!UF}e>D?6RGRUZR!PiZMViGb@p?OIlK5ulm2@4*FnhBgxw99%I+tAp-zN;}Q4 zhJN>BHV!n3UXO+>$?Y04b>yaKx^XBcVV8M2QLByPfwp&kG=_N!=Flc-N=|UE^0diy zvdg@D_CT`cIpV)QTs6ECA^PhBnsY}D8Sn8_?kde=n``2>9gj+=u7fJ?% z8dZ(Au4)XZ>COsN;~xo{vf2R!1jk%ee8pjIJ&nw9)_@q3)Ogy@ z2a8VEQ|syOH@Ni_-x-^MJfi9d0DLQehxiy(2|5_%7?m<=IW{RpXtco3vjC3CF#|dlm%?frfDpVt}dGT6T zDsQAf>lR!hKdW+jjU-f8l_n?nGoYjwPYLLxk1 zyJyeuGRO!uKi4%@a$mW~&>m&ry|f~S`PiTCGF@Jr(sFwe84Ep$jJGl(L!4$P)n&#v zEsqX|=_rLGWs*e$hq?Tm8lH&T3=a`;+=aE%oLOBMQ8o_o_6Zp_U@^857xBx;^bu@r zxwdP0S`~cesbg%d?_H&cX2ozU->tN)$aXEAs5!Z!RoYdwXfW9!=^|GqYPCyuyS{_T zo)73UAW08}{DV^6xO!!9#e4S;Xy2u)F@4zxSC3XXCawh| zdpBR^BkFwjcP?-Z1>Z`i!1*qGf}nI9Il=+(4FK|sIT7#2UeMy|#<%Cxjp+){9p&M^ zXB;OQ?Kt7p`qbE@Df2opTcdYK7FH=Ui8{378%;H8*^xF&BG-=9zo}!Ix^hMWQbtb# z=;J*Jpg++CP-+rTA_&2?;j|nl6}Gj7x6pPOcUNXsykALz3IdiQc(q(a&E~%OGI5G) zE%9!Rn$nCnVuryUi?%wR83!JP#Zo)1Oc%TFvm}@xS;<*Pt|lQ}5b2#qPn6?xuVcrB zPI1Fl+$iO6RR7k8wTlS5GC4k7r$0Hx2ny5Kq;P=&XYvZl&Rj^sNgUESlJ2f@#vgSG zEX!!L&5F3@yU!00Vp(?oqr)}X@=ktJ#8@Wk>l2FH6+!R2-pcsjh3g=`Gm?x;sn>H- zihNGSdXP4veNEszELlP3^(1p%>`CUtcab?3#py3fo!GWK3cI?oK6ec&P2e*nh8z}p zfw*Xq`h%pRKy>kNlwD^YSx`cWhpH)6V0dK1btSP;HURl zSCX%Y7rOCXBC1M{n((j(LR{i`$zaQ~gCI;;R29u=(y3o0^(2%QdlE|jQg;wQJYyQ+5e>}1_x8=@m)GRou36z6Y`*NmE5?k2E$rCXsQHSEdt}T?I(Q-^?%3P# zmJ6D1Fgr0Fmhcy7N6dCWVMMhQJk>!LR$IQSLX5%{dBk)Rv*qrx7#GuMgGh=OEZsYd zg{I}3Y@d$A_k&JkZU=2P!gqoU?#!0IZwARWi*P61W>m?Z_|0&bt1O640(bHN@SJ zkDA^Gk(n8yE(d@A_WzHZj#W#FoUb14o_f#nJnKO{2HaqFX+_{@T*@mF3qO zi1O5E%&jcVEG(V!T(^ zV(B7xg8!Q@I@0|2%LkbM5LmKsemRt`I0{SoLtAfDZ+lvBmU>!n{tsOXmLaru-DJP} zxEwy$lI2cY7Vj#tB|ynBrp)T9`64oZH^zZ* zg>kKW6m>4fiZWg{tA2>V;qZm?g^AkOWX2A7&*ze24_(H=nyBSGn7){kqM7I0bnksy zA8XQ5rM*#>2H7Eg&&dQe;Oai{^F0kXI z9Fm%P2-!iECxfx3DIhdpWysDnr#md7WPyY!tPGo!c_K9*gf<12@j%lQpn+(;GjmG| z%Owp!xyK-98aSs4$QWZ;tmJ#5Psu0GD*PnBg2!gISwu$1lk4-dYx5g2fO3kGMDoZu z1uK5+}MXVNC^dy1PP|~M3qzWdT zRxP9dJ}bloo$A4NEAy}qsCfGN+RF0A{PLWPzAWT&H())0k69%*t@@ldPY8g*MQ{AuF9V~AXMwkvQ_y5%B9tcW6O7M zR~4PAZOhenf++>z9#vT1-X8JyY8j6spPqS z=QelZsq*Px;f3={EDgC_UlqbKrn+bl#?a!y6D@E(M0OxJVyLT}!??_m(&?@P+(m{@ z)W&M+#scRf4q0MH?Pi}WY>-Dv#8OvUX3wi%es{(mvP!V`Qvcy@tAof1X*ciyT663QyA&R<3rS%n_$4_pxWN!<cd!V^wQ{LWeX3Dh=DH;4x1KLyr3@>TqgFk{aWp5p{O10wkF(*J9gkF%-5gH zkWSdRSg^;Mv73n9R}+3{YQIHOn8k6|H9&+4$l=Sr#wr|)WT?_Pe~SW2SI zWEal?h@GryW^+X_{sIj%RUAah3}BCBQmq|q2cO0r{hnSnS2ykptFMY#q}r7B=@OUr z+PzL1uJy|qGxPAFE~al<&8B-B!s`Jnrh^oBo)$>;0tcFY==E!_%3ECWVXQ%`#r$Ms zk2U3^TgS(0wW$KUe9bC_m#@*9(e>%+=G4v0UhwABmCdQS&bU1}yTxW#;+L8`9)A++ z@uiuyg_*f)*?9_*%lD2DD!+*G*|}?Zj8F181C*utS3Rz#flGuna2YS*L^>KJ`h`|t zLEvOATkW0b<9lOoy#A82GI4Wh*$$emOEYg=k8XOkH(wR+lVwB|`leNdJB#REPt@wB znP~N4kw$%5Uvlb+2Ar<$XN`oAryY!*;RQu923VDSG+&l!p$a*VRhVyQ%*5SPkrPf6mR{U#RrSA@Uai5K7y>uT zV^I>@ksE3*O^eak2UyY2Am#^swQBy8IL+mH>mF4MmR#YO=GwxN7<_qft z6GIJ(Wsb3*&KHVfuWEx3YH%MGZN{-zp&YzAsmS=#Qr-ePY8ClW3ruI}iP4|i}qD%c2G*7u~`;xkN zcnYXbY3MKYq@n-rJw9$XUN}EKlk}ha*#RxHFBNh`tvg6C~8$TAlyZSX%O1qQlG zQO_?!dZr{9-a?|yU|xqPl+NiG#R}9M!t2SJ4pf{&vPDdy9I%)~_@t;QEujFeG>alS zCt&sbhSN(Nwn7jF7u!@`yCybHRbN6^8oL z`m&CV6+M34Igk$3^tvN77P(=i2*?RuptXls;k@#?zuSz7f!#i zHWdT?d_zDSNouz6-&`H~&`HC%cyejnyz}*MX z8FRx=Lb0^R9~Rx56x{^pTob>KYQJ&FE7Ol_zdzh(7q&Xiguw4u4(7XJhe3bfje)XKUW)#I-_9_c%yzoVVFv5IC?-0V?EVy?0_1^d#d61 z0X0nIYZx#LqZ76w%i;4LpR;<8U?K zhoCrlEpnX}tIVy;!uoPx1r!n;VgP8UP5x2O^5JYyTGSA2tD?YK6&>I~ge(s;bIWbD zEx+nIa%QfH&f$Aa6L5WfPZ(n#+g^V4s>^>6;w-~Y!SdGqi5{L}}&;~%{; zcI!mYf&AF-s=I?-Pb${Juc9U;B;GKOtcL z^?+eq?xWHEJcVZaTbPT+zrSMW9{69TfGheVf zQN;Yj+c$Ca*J6%&b3bHJEtm5G*-0OBO3T~U=1bo*UQS`kso}=$a-y#0p z$$v`geU|>U(c1ZP`X4LM|C*xz<E(t-{-2q=W|3lp%du{mWSzydJX@T(dT8cBFxTJ*H)HHQxayh zW^zut@4_Vh52_v=A6SaF5*S6$yMBRZmyY!pJ4W3)xMOo}yhCOezTRmayWhf@j+Iqk z?3ifkgkbVM(9cD zpAhLMB<#S}7*E?8J0W3@iTbc3|E+&N?O?Nb9Qzb=X&i5pVWa!3Ve~y`7=7=f{SEDH z&JBJT)(F1N!Mx}&Y>nxI-Id5_$B8SGVP{B_D|nPGavdhKK?ae%>sfv*)1g8(@sguV z02!LecC{0;NTvZ(Q5eQq+fO1-=3xh+<+0nUCRiLq&Xyy0`+90SO$8dZ^ag`vBT|7v9yCgUf+Uos(c3g5QnjKZX*##1$}&)(?d`3=R~;avyrAPq z5cJ4yM|i&8-fGFzhmgtxL{;Pc*bfq7I(*Iv7<`{Imd5|DKEwETeTMO;ea3l8ROLcu zdqKx+jhu}*rG6z zh*EjHzDqJ4mLM&?!6SdhDj)2p<;!9!Ibxo*ub@@ilq`Y4t5gRcfojwB9oJU`h0#gR z=FYydFledgdd!Lyo9Aoh*ei6N%$4QYjhLnV&)2|FR5j#ri#tu9DJtZ1cbV@5io?K9 zjvMbN{w1Qh@eUojxh)JVxbQ!sU711KxPK;oV_JT<`2DZ@0VBPgUN;QmpNdWTxM3LB zNPauFF80}Cs}Gv}1HDd1){pA#rLzY%RGl16MxR*&ydJ_zxci&zHf`~&j9Gt;vX+Sgda1Ex5U4{1({#d zo`C%CwBJ7m<5@rcd^i4l5B~fYuu3HDa4Y^B_~$abncW^r|K`PKE;);E^wwHp6@ZF3#JvCFL0 zYLocAw0?a9FO1^%7Mr|$Wol}oa(QgJS(&uQS!H@+>vCm!i%r?%mnO%ynyiYe-nD9C zMJ<+)URxE~ZMEqI_D(f+n&9K(v6Wb3#LV=InEAU8lbP>ZoDLi+Gyeq;rzaz;E#6c( zfSdoPKgG)UuF2H*ca^Crc0Foe23k$X#_&&2$4)hF>gTp^r0M(0R43bi!v~)UIlJHQs1$;!YX=R31f7J0*GU~D0 zk?r|O)%CMm47(i_((vdl9=Da%La~-P~WHmX_<}yILtvTafhiv)eG*mT(x0DTh#x`o*S`N$BGn& z(4E~@I}D@X_I|a+d=^=1N>DkKNi|3uL5(!4y`|V1#tApXIiuQDVCwQSa@WDNszhy- za7M&)c9=>8Yw|>N9@`h%Aj+0;T;xW#=YO| znX%;};J&OI{g*j@I`M!hlHD-5lq-?RYFmCQ6;&XzDy7wyNsp{O*|@~l4ZGlr4BiA> zCU8FZX;Bvb7+@KEu#fyS`D48Oc>@~&I2;(?)o1h#7;pFW8*dwbzt8CVO~WvLtk3BC zo<5`Rw++MiKaU!H*!z9^aRZy0fjf5$P-F1KpByy?R*xIT3x+XhzARlP=otT}r6&ir zBK=!Iga-*=GQnZ5@JJaXuNy%IP(h*&4+DI3)RzpyKyah?66$%hfx+W+(utGwOyeiw z$o8$|z_v9?OZM`teHL8~qaXz z0~TQzRv{up>=Fr$NfCx&fS4u`Y5Xz=6Ap!VkSUo8ko@tl;uB3(qo4y3S>;o-8tZBbR$2`th{LU_6{V&~EGqf@jHCw} z76AM>v3y&NY8i~r+}3t8wGWjw6j^>tRg%NB(`<#L>Pb4jCyR*aENqM&Ut3e&R|>{% z!}&W0iU15+*F=pT_E<&W9C`vcHP@Dp#g;x6SlP7p(7`C&QAX|@72Vj4NsH7e4a>1s zg@8#|1ocW%Do5(jZO845KANjV0BqTnq#df&zqFQS9I2%~M-g6&oh~b-`Ei<$Ii~f+ z4nm~^K)utlwk$ufVwH=j5=~WG?XdDjkXn@?9<)NK8kVDbel5@8p^sQ@NW?^|Bsi3p z)Xvo&xnYLZIliFm9HmQYz!h}aKuHbx$tAi#Qli-kcSBDJB{2$=+w%psYd7?6<3y)Qq0pmav zv;)-~mWJ4Ox3*Gc3mC*KN^GUEk#kkM8E;!rx^iNniQ7$Rxe8Ti%W+$sPoXvVpDXCqXDAgC(JF&Z!nR;IE5!SPM={0<_^5na>sXVFK3GZ20Wc#))0u$ zcz41WCo=RQxVTvuZmeZGsfY@5Xj7^D#y zwqRv5P}pC%9@Qp=hcYLc{r^p^CjqMbO= zjCL5B7%rD_<|rH;bc3YYzLg}^W)$pb5)SHk5HcSUh3_h4Q=q)e(M^figQ(i#PLt0< z{pcO4W;sMPVzzQt09wr?+KMZ2rzx(3$i^XfTj|yX!$36#PO}r!7)eMnkDzlrD`rZ; zk~z&po-N2SSRhfRnN&j-x#6~MwgHJnrseFiC_xN+RTRs*%5B6+)UoM#1zEMkvEg!A)+x002;IgGx5Mdi{2g_D7cH7yTNFTO z@abZMBA43xc&@$EXzy6n3cFCr3iDL5LQbVOb2XhsO^=DN4BOQ>-gZQnf%}E7xNCsG z|Jfq`8U*#>rCiGoqvb&wZ5$b)xyK95AqVxJP3uPzRhXS-e4H>%@absZ9b;*HqR;3X z?=#My;4O^x8RyU3*lM@iQ&X?DTBGB8wLatgNgRT*sN%5QYM*ibR5d*=9PKmCs~G+f zYmJgm$!OH6^bsEPnbLk|kt3s{S{Wc=JE1S9Hfcjn$6NqO8lg(ZvaMM^IrRn62?;H; zZP}{tpo^B3@o~)MW%e47c_`QJ#IBt&K%!e|&aEJ>(A`Igi!{^ng2;AaJFK)V1(B_~ zqxnE)bJ|^VqOLjUpTq>FsuWS=R9K6SIuc8f?!84I*B4Nc<_`+Ju1jS)7BZrSuI^MRzbl;!F10!2;7pz^T7Bij!D$ z1iCUdT-wGFC9<0_W*@Xy%j|dyJ2^++MuL4ZRpSW`**}a`CR00kDdcGgL2pMF+8r-( zD~Q1vZbzDfECvB~!R+xO76eWCp+>4Hb66@F`DK=paJ(@BoI&wK;b>jkeCOmrAd(x#>k+s5Ml_(mzaAk zqd%$r3y6w~>#>^i;5+TiOkx7E;?`_dTNn`cF7Z9kw>18iVSN6G@wg!a8t4mtl}=zk zf5dpEG`l`ktJSLS)$`mqiS{dF>5I^y3*^?f!V3adMh&BH$1wW7%`o~tV;H!b{nB6O z-zVQNjKQP-pDY#k9*vP1uVq=NXzz-=o&^EUfBx6SUIc0 zbG3>$o{?IOSQw1%TWt@UB%&&ue<-4gBp)Uo618g%;65aYo6FTV0%fAb7-(6t67Z0` zTQAcf)`ZaovnytD4@4uzEs1{MunTm*-k{|VA6S90w%`MSCV!(o`5XL+?1toM9NxiN61UmX6ys68?v@-#@JV{!#7s7c@HjnD+aN+V3CNe*c8_ z`zLV|THx>{EgiSjW%^HP>0i-)e^vYaGurR383rAX;`8%bAAdo+cY!bsvX8%H7&NZ< z{Ib^WuNVfrsOj^oTK#ai2Or?`>l!?^tKbQI;7%cV>FXN&KiA-YOE~G{1D6X4|2rD| z?`rVBr@?08SL-I{lQMg?mms)*>`u8IJqHKcF@fg(L=ZfjmNXM1F z6jg%%5Yk7GKAout0Wk*0is@I8{!fba%pmAzS^UqJdF7wdl! z=`a!vE@bLoMEa#7{4&y~k-nIL|9+&~1pl1QNS{MGL;Ck0L-2#KOsOA0?)!?Z{2HkTwo*zZ}w< zRAlvKvVI&{tAf+Mn92GHWPQ6R^+klJMCch}lAlD@e|n4-2Qo=f&yd)_!j~52EibLr)v0@ z2q)2#pA>CN8dL4R42bU(5WmEme_n6?R{-!`I>2$)4?9VQEWZk%zbAn*DEwLxh4Cy3 zzpkV3YaE4P9fjY}Q6K>6MVCS1H+3X_ErZ0@i%3jlk@)925?|*?;Nb-|48Nr#K>#O$ zPLe0YZ|gXGJ%hvVAnSh=H2QMcSo|&^{-uEUoe~^=4*-9p0|<}43?04!sDCA)GC2Hx z5r^Dh{DF?c@0Z|!>85ZXfD=xf_*NDN%shp|??dIZ-t0u`@+kHn_~3hx-$$m{UqWr| V_)cac#FbgH(ri`8t5B3T{$IF)K!X4P literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224223439-Config.rsc b/MikroNUC/20260224/20260224223439-Config.rsc new file mode 100644 index 0000000..242b311 --- /dev/null +++ b/MikroNUC/20260224/20260224223439-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-24 22:34:38 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224230007-Binary.backup b/MikroNUC/20260224/20260224230007-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..daf9f37367ec07983e3d09d3bd5026083287c62e GIT binary patch literal 307416 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�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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224230243-Binary.backup b/MikroNUC/20260224/20260224230243-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..7cc22deca40d58b884ed633e09a96737fd9eff58 GIT binary patch literal 307414 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�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 Tvk~ITELmx`D&$ot${YVLIqpBX literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224230243-Config.rsc b/MikroNUC/20260224/20260224230243-Config.rsc new file mode 100644 index 0000000..ae317e5 --- /dev/null +++ b/MikroNUC/20260224/20260224230243-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-24 23:02:42 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224230525-Binary.backup b/MikroNUC/20260224/20260224230525-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..f33fee06ecdd9a52db5c3483dad8ae259e932581 GIT binary patch literal 307416 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�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 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224230525-Config.rsc b/MikroNUC/20260224/20260224230525-Config.rsc new file mode 100644 index 0000000..f0bec82 --- /dev/null +++ b/MikroNUC/20260224/20260224230525-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-02-24 23:05:24 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224230855-Binary.backup b/MikroNUC/20260224/20260224230855-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..c2d8caea39acb385e73121ce5f8fe26403214da1 GIT binary patch literal 307414 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�%wwQG+A6xM%i&shB$tGMrm+&jyIcXKLFym3Z0EWQ1S{BoIT%l1t*)K-xVOgf zd|K973$kBA8*R*1*R~S}6q@>MXS5wtloey;Nv~TI)OK^*EzY!w=Q0<2yvN+FkJDT; zr8uBQ=l#QD#@#JyGvZnn2cPyZt6iv^8~@Uhd7@>2(mU-*`-U|W;s*y%#n0PY$2p8X z```_w$L6?JlM{X0@{6H)tOV5^Q`zZ}k6tKi;mL_Ll@4>&_qik+^>mJveA`)d1*6yG z7O=mPh?|+;);!>8@N|jyOb?|srF&NN?3!%0BwOJmY1x)+g3n!#Y0KD?xy7dAWyOkh zp51#kYKpjI?P`W}#htmIUe)N0*=D=H{+;aI32k+2&OC}TIi&KSb71+vEaSN23P#el zuil#+UwN8Q zbI6Q;bxp$dIHM+NveZH+bf4NKw(q;^TIXu8Vs4cOp6py@)@YxXSfVGV*l~NS^nmk9 zbI;7hQw{ZxMwxc-yp~$(bK9k36 z);4G4%xT$_{pzE{(IYq8!hQTdG%Ba1;Ct8;7hUQ;J?Ha{80*c38&eWDYE&FoT9czT zSis1A6~`!WvQ~^)oRb(3WUp%9nAhKz>w3bodHhrr=@CqLqMUKwlpttzj%O@SlNs%>uri}#$ITS0D4aLYpWU@ z4p@1p+Ei`3b;^uU={i$CXX&`3UfH9@O_Hi#`E2^$^l0g&rG6HYew3|mf(J9>98B^a ze73l_W2Bi+R|#z#b!8mM{@&Z0W?JrqhoO;usW~hM?drRn)AonA z+KG5tw>~jwm#b0kuS(Vo314(b@nX)wtJ}nqbL$Ep2Oqk>xScO|<^r*@Ch{$7?l)g*j zIi@!qpL^C&!_EiYokvvUtYW@Cb@mC~FRR{`es$R|B(z z?r_Hq3z^5JuT8Jp<-SYxv^!&-Fgk8Xs8tdEV~a ze0g=ncJ&z|&Sg^)pU9L~b&Qp3xiI>Y4R6n$@ON*8w$%0LOdP|UgN0lSV*|(46 z>fE&I@|SZ@NOKFDay1%bTe(lQd{gi*=S(L?P?@JTxhQqZJ*@GH4th0rR(Gf4iu-Nf z-C+JBONXQ#P%pSe^r8Tzv_@oLh0?0q4a*8qIBZwZgil6+!C5jQy2}E47EGGMxR+$qZ(G!obI@J2;Mn^T3Talo zhDGk;xrIkrhqlMHKTbdW%m*Z7%Hb(mRDhE!CJBM{91s_ae3KZSSpKm{}(DvmaQs9q3cs@FF9>TWg}t zg-0gryglx=R<^TBp79Xx6uax2GrOOLG!{AD`dRp18ooLkm$mQ4 zlYLVgXBgA8Dz(jtfeWrpT-I%yo#m6`^lB|FR?AW%?8@#K5>IJH=ZSgkvk#BuR2&Ff zXRRc8c=IJ@oZIcU`g&3!YqBsqH_+YvZJbD{6UuG+=FgJFX{s0(5m%opkG)s7z{YgT z+xNUk>#;E#P{)*4IB1=j)6Y!yx-v1@)S;^FBwv*zRnqpMlcCR-&FPpBCwM9<9OOV$$57zBp8TIh}CGA{~Z4W9&yB;{C zaAKOif0CU0mlE^wDPh@u1Ba-o{r5|EZd98bSAD5;JF|HOE6zKz$!gaNxar;)kmYY5{Vi)_iYUIXN zxrh4K(cW4fibg@6vJP8bOuAvIKoQG5g5NRb(&P^v=O4Z@X6|tm{pigx-IDe2v0R@w z=i1>K+`hb4QLTwgJX-vu;f)n-MHga9XN$x}K6R3RayMYbhkJLzlIjv9UTkGhEIq2l z91S8B&6cN6)I6Oq%kGBPm8>nOvizuh`?o3ZCP&M497H(kdiQck5AHPWefwzZK3(M* z6N@c$uIX#PY@aKYm$+#EY_EJ>2eq3vGr*ki%x4SQydIo8H1Ur2<8#}p=WRI6 zI>WtppcQMMHyEoxLbi&JY3oIqPb#6McQ{`$EBcULB+{%v+>!n+>+`Y9kPT}|oERgw zJd&%qleT|Cu(-0Ewa#3QlHT)=+Yh)Sj{3X1)`V>A(g}W=PB`AebqLkBf1q62mdy1{ z54?9p&$xU3qb_^VQB{}2=WU5I$)0~*>tMp@(RV(RLyhMq_kMn&GQ;QMjWZuUatB7o zc;IafI_B#aojEi2-t=qP`lT}>lD2m;y%_{u$GA{ed)e^Qxh>1_t4OEjPp>iXU)2`9 zK{x44eaDrwo1t298eJC~R?hN0?KOqRHO@V1UK(A$B~|6bPCYN0=L=H_tM{077jJD} zdSU$XGd|B6zD$YTk)Km)KWh5Kvkyb2q7uq@kvnv>BT#$7mzKgyqqnCrj~w2{ zyC4~mYJX4*oi}FE{&lQ1XHVFDx>-Qd+ue57yimI5ah{U6%;Rxvnh%v!UC7wp^67o#RQCX&5< zPO(_N;)%+GbLCQ_js_E!6=+;pIBvD|yWL}Tj(NzpS7nK)g}s%>(r7z z^qzl7R%~ia8oZ<_&RSmWiCJ4QhIqdDoFvBLT!6{+%&jtM36-e_TAm#(HoL6hXOSrz zb;s!1RX2}^vCZcbqku_7=Q^oFF*S;!l@VW3LY3Z_EJ5e5oMmC!_EFyVP$AMHy5|&L zz2vqPdQ@KP)kmcJZVB#*a=R9n9|_%^H(6#U-y4H&Hjjpnkc~6ZH;bxm*>zMj zJXhuJS=!e5T>`Sg5t;LCJr`Rzf}1e++S>8Sy{CdO@9me>tS5<+Hr0Il62%{d-0$u- zpS(zIooaLbY$wx=Qi)P z4&dsas#DsY?N7cZ{Fu68ia_J@0S!cFq ztt1sU#++eVC`(9)tIr93`Z!;P_KZhwHNT!hyR^=0?m>sZQ77Np9ZGrLm_6#yZT0%L z!I!h2zl%$rbSvQCngfqNPBO4Mx#(1rTiDWMDTM@-_m#}GwMXLK9NBsvDjQPkBCrN z1O}VTBJ#*|DvwG>XjJ%IKSCj}NC=fiW3y=-8js7RFeqdmok^sV$qY7)OX5%H_z~=a zM8*%{7JMJ341tCa5vsX0gJ@-LNh0&fjUU3|rDESr&G=WC4e5WK*^sd?n`1zrTU*k| zR4WRdKpy^;ozXB`kVO(upM}}Na_=hZ8*WU;@9^W_k}aqV{rV0@@(&~W%S_?DhRDG< z@d}%;HM~}hkWH6&6?Te#5?vm$=Jj@V%SAI~@0UgCwa?cm>tiAwpwvYBC^bj)!a22~ zM)by;CHY0$z9?`f&eePB@q+AiVOAV*C0Amu-E`UZlX2IuDf;t5qR6cqo_fA#$u+Xh z?Yz)Gf8gTWt(exzwHNArrYu_o(w;Op+fX}=u1Op*yC%Q?7%eM%ij=g@T zG{pM&1-ZKQ>D|k=?JQq$WQKp}q|25QLJoiMo~)J889gIY)#zb~`8%tr-b=-Gm^N=> zekD_=D38va`*@K-*0qfLJLW%Ftdg>j@y+Yje>GE>vs~;nax7WNOMAUWnDL{rnUQ5v zb?Fl<122{x>igW^YW{g&VKF*Ww0za{WfETPR}ycX%P^VrUSi4$c1LyS=@7SoiqPHj zULBo$SYaW%RAb}Y&^});Z~Qs}GtAs-?c7Z#UaMRu?!M|SBT?gE)H9I&+WTRQv5I|% z$Q;itb2r>boTd0=|2=Gl%uKNzx+|A#UXZp_Azj3wrl{AVP`AX~!dX&1%cF?87k7DE z;)BT){O+93X<^B($BOP{iQCt2>B!Ky%(*@P+16=O$8k)EVb3S07A3PP-?5%0hS#lr z>tD27F{$`VbfNm5xXT_Y=gSz8B2T=CwDC$}A>!MnA7#ue{j*Hrx5@lAnGx?O7@AG} zzujcMPN$?X89anS zMKCkB_<7_dJ~{EY^^M5)KkD#riM%66^p}yh=xK2cG`i+_KV1L9^E6Kg^ShLzO?hQ1qni-Lk+BB1hxA{lz4%49GvgZi+j<;o9pJ0c;ZX zNOmMloH%Ct!7<$+rdl<(-@rU+pl-Z+g+oRa@oc)`j5G40RW5_aH{8>_ocn5i$lZKn zWme+cxdYX4t{FAEQqvncI>O~|^gc;b@<>k`Tjx~d^ed6qm~}e-!RGDZdyiRH2G{wV z{ODZR`#*}jInNdcUBBLTO#LL|^<7n3knzoPU0qu~h>m|%cjVRk#P}5J^yB%<4ya#T z+GbVNp=z?%uhV1Y%GI+YcUcnudzPk(#w|SRqws0=1=G}%=vP)>2UYr zhbso&O$j-=Yet_@V(XFfz3POTKeSYK}8D=iX3UXc)kOua|SO9S1s;c5~@MmF#Kjb}>1fvY#Z=wwj z4h~iLaSy9@`Tgio1z8x7Kg;l6On^fJ@bs7J{1ODjki`EZz@M8%@~}5vU#>eb)%eba zeE$pY9+8jQm%Kc?Pwuil#s1Z0=|h==(*iyy`4-Holatc4@~)mzeA(k!ckPkHqTJEO zGv2u`=yKgx@OFHx!y>8Jc(<-gi&aWZcRbs7^mC6I6g8bb%oXL!gS zS`ju_*0y(9Z&2&>P$bM{o(*lZb720lh6k^uR$A<6P)XjH+q>O%+@y{r?`FxC-+6#i^Ec=L$Ve9IX7yOZQ0rpH)GS#cW9TE^QPvr zrDxbA-#=dC<#Eo^IVY*6ob@QQxbWfjtUAYsZci##T612`D!+T9Yip0io6`w>X<8MR zQ*U1`CoX*9d~x|k)xD`m{ZuPl@*U}vU3N3p1>lM$b{xA%-*c;a*Yi{H1#w3$D?AD^ zD}(795(#ZS_bqeol9c2nXFelk?_z77Tbm!#GoLn#)ONLXs?0Rgxk%)~mI8fF-l`R~ zWfr9S*jD4aDvTx%(7pr3ySE0}QTuGS`K6sQoX~iu2~req_Xu`>bnvC@{MqWp9Vxss zBGtD&ri~9Syq_Quo$h#dV?$hVWrCMmOYHcossWEqhc_hmkG{3ZZYKBRf!gqR`bn*f zaQfpU8-4uji!P1n8coG}UPhITcJo7Ioq$YO(o*wrz;blq%;wnvwnou%Eg>F<2R##S zCiXGzIyQ?`K2X2*(O~=Dh&=(!`kU8z3zl*+*1U7RT(cDszdLH-kp&XnVBP5@E(b4E z>@xBej znnmy5kA0hvmax&Yq;YAT<&&l>s`W0%=vjK%qSf~~kLmHN3zwv-PI7X0)_A0I`9+J~ zxrB|@X7BelynQuZyi;0tT*Q|CFO62$1`F)GKRENc$~#Rn2Ef{PZHab)G@H-mvF%M$ z9(-Q^$u`GXseST`lrg8BKfI!<+I^U?^x{T4*Y;1XNExp{F59!zw*}MEp79h(iMxL_ zk`I2GyoB}N~lca@(|ByHTeI=ze*-8wfTO8hpVl4S&zkgk2}rRxjsrvtwk|M3hdas zh9SP81F=ibICJrB^WOH8w+|<+*|c=S;}-oJH=381aV)T}OZzldICbNlrbUz&PuiTN zGbp~{kWE>!eb=Mu*=z5-H$}E>l6>5vSdZ(VWuLtI-0|JQ{kms;qnROM6$dK4Un_2U zd=5$0GvU3OP?eQFAK%=qaO&+GPRonU2C**)8HMc#{yz8i7}Cy83%#}1A@H&afe^+B8@FMj%) z%jr|{6i$)0)+VlcF!s`!WH%#7T6qJ%XVb_=oM_$W0c|@56MrYe)QLZabj@^8;dcibglU`K@ zk1I=flIJAJHOro{uiVh*R7Ib9$u?CFcHsKmUOUU`jI*0&U{4=Bl16{;S-$RB@0Aak zTOT@#UAI|3x+nKkdi#0%sGI1X!yjaG3a@~5Ys2of zTw+8Te+*ge{)7c|4eL$ROis(tn|JK;{xMY zewSaKYS@?YjC=F1QxX32<+AWc99LmsVE#^>`11!sUf_<2tM^`VJ*+={?V6{z3uJ~F6s&V|iK`zdlxWCva3AsW&m zx=K@7mG$cGs#3O8{hZcxbvIqzGlH(tOjKr6Rj4u}QW23=U7G1(gs~CgC7G8o_(Ons z8rC2LHV^Nz2AhYyYe3kTU0^X7%(sSx#TfJYX7>Bfxvz+ftgdbeuovamUv^f+eVlvl zIp>~x&bjCQ>ev1LrGNe6FFx|YXJ7uU-};8ndui&~OKV^C(Qo|jkA450Z-3kB_4E_( z|D5mrzNxJr{D$T`FYkZq|99 z`A3bXe(L-G;@r3W=P$qU`hWiV|M<$AzU0MMJ^1;H&wXC&D^K43#4m5%JpU~--}H}u z?UVoDlRv)m(jy;g6s>|#OLUf*&+z4E_)>G|XZZ53mM=L#;WJA7XO#HQDDj_B;{Q8W z;weDk)a2C3=IqSO$$G1~>aR|>PWUZ5!S0`urBB(M&Z+An@%&EzlQx{H6%*K!5g3f2_gP>brkgFS6+GLm(}m@*pKInldl!H z-|jW^?FsQQA&v-9SrbC63n4az5Rnif6GHTa5ZgkC9U;UAgb*(YA--5pMe!vk)jt3SUnM+_u1+< zd}l?xNi0sj9;EuZ5;_6jJs<=U%!tF{Wzg)9cpP7^#n;22uZQq;P>7=sbbG7qut_BU zxDcYX(d>?=L9!Jj<4H_NIssVz3$rMF-YJB5r&ydsM+bzcRK&}N@V+9%(A9lH96eGU zK70An`71Y`U0gUjLTx`PUOsxb*$#s!d$!{@UsvdgdwMnvG7K0Z?3hBpJ|V<$^?Sb% z;%(~p0f8a#=b%&m0p~X`pxZel1h|_%!xcPVoU91(AxIj&HKk$zec;-}OnoLg-dALw zDRLO80kg~DS}^gpzGC}Lu_2$VHRpn@qkW|gm{JE8!y8Zc19Z?7c%T!u+dA!iSnBCl@69Y2g}Y2YW#janLHkCo08WE$``qA-esN1H zJ6^wCuNxR2%fr|X(+raycDr%h2CV|Hw<}=q|J%jlMyXrDOzmbZNE;kUfyrwOcw z!41^vVIhtl0Og~d?RL{|wyUb0S!aOyHNQ8856|EL%e zuX?9>p_4+GBWu89aD9txaA$@TfR?aLaGS=|xrlkgflw0gdd-H8MkuJV=eq ztiLE0Cl5U*KD1x_!5>w{qi5eL>K}cpIPj9F9DGSs(DuGOSo;9heze%FJSPsxD?-pP z_G2us1KbZhCk}nz0m0xLR)1g!`&{^m5WZ0Leo#Dj_^Np6Jy*rYzWu8B@jtpMe*Mff z1I2^Si3<9lq3%ORhj!@*AOpq&IT)$`{LnQi(nN0fQFCp*ttNBMnar9qnRI2b5Hy+d z>N$j={tdFwzab3uZwN!(=8*IJv3+>XGf<%!IH<;Y7{e4Al|%|IDi2IvtWDKS&F5C0 zHZ>0sf>2{02L0g7#oEk?6ZLnSiGJ6QT_IG9k6z1HdNsN`^dL)-{pb#Vppl2s$i#_y zZD#URecpC^_^N5)A?ns`;egx1!I_J-sS~y;=30-nzv{ta)oG_!kjUVw5A;=?w!MO~ z23LKsuj(l~IbaQ4wSRIBp(=j*@Go=pcBB0Feb~6ni z*L1H?KJY=W*lpnRf>KC^q@ow8c&@TfLYPSx((Hj+z`2US8w|P%E=h zweqL+75tA?`v6v~gUA7hl@chRjnUCpzvn%3`G2p%zAnhd!){hv3)@+c=yl;~ECLFD z${FH*nV#clMk5Kr%4ocwI@^2dZ&rLAC-zFYMDPahKEhaVE+M;;R5M;{X6#~u>U zNX1VJAwEk8@v}5!AwF9O@n-B(1qT}Z8zF=gLi~ad;^&1BzbJ(Gw?c@2CxrMVA;iBI zLj1B2;{Omr{GURIUlBt5oDkyIgb@E1cAOO(Sq4HY52u_DBqgb@Eq2=Pr7AwE_S;+rc%d`m@$Z>{_ctp-%}Cddn-cxPZc5laYcyls|fM^6(K%e5#k3bLVThk#6PMC z@k13M{z*lMe_9dZhbuz-NJWSrtqAdB6(N4%K_Nc*pb-B{MTj4-2=TvGg!s7!h4_hz z5I0nFNFAyLWo1+W$~bRnRe%k2gHz= z1Qkr-YZ_lO_&R}|?@1ws4xYlVS$xe4ap=+G#56-+a2lns<;GU~T|x{^5~nT*G4$Fq zLL3^c2ys@3q5Y(+oJ0Ndpu3Bx_awe9;p^S_dP;~xpExMQ!{X(k2QSm+T8Jxna}{6L z@b$Us@eTZO6JJl`>lu8#2Vc(#G4x7^Uq4e3L*i#EV(69k+j&}LqZIFf#sWrgcy2&RKO#6`)V})7%)Z_ zfhU9*YK^LPF9Xe2@O2em$Avh0FpRprj3h@5itStQMcem9{POUHa8oS6LWpYz#8KE% zOwO)n_AgE{4>3P6Z!w>JhO7R1xr%1`)5ul(%DHO)-*B!X;YF-PT;*~Hv5Uh##7@Lm z#A3v3#CF7h;Kv8zUe@hp(ckRFs`58!vD#nCRuoL08=AJKVa54^!PAMBN{x zJucNfd>CGfLx&F^9$fc(9((*j^!p>I`y;5kA9cUyvBwXh?)Nxb3vCxj5+sD2~7_v7j}3(%-`wnV<@v23 z*^$o#!Dg)@jvgORchW5AjHk^c>}K+Lne-ybMHiyh&2G!jf_ZsoO^Bn9@MCHK^?%rb z3`*Vv)I$Tt+snbIE(KYyEBW#>c|O_-lQ<%pUyBpTP^5tDOetg>VyEs-I~zx9;rcv* zoO^Mh7c~{ouTd|Sf{gn-A8mbOKj5To8`z&Hhuve`o%46(*^QvNDKEr{WE9CI!XH5{ z=hoZts^6CDL3Sxhvzy)4ysSEZ0GY4X0CO3?-R6cqJ^(gMv;4y^rD-O6-{_|V z;Rcungn3yldkUyuQ}W__`yqD7pjHm%p2=XYoD3GrNI*YyrvH(J#oW}F0Gprsv2u9# zIQ935*4F__BB0zvz+ULX!lJDX@ZaKt{}O*?*6>-x=2e?3THJ6cV`)_Ty5lPrZ0hGpQ}R39*kd`$hu4*grzZ&(Mu zS^b7Z0+Jq|zq=207bjugcti+VabSIUtq_&h3sHH45bz#W&@Oh#XcN{4nCD@EKo&!^ z4bKsF(y%sQTqOKyPYD0m5bp`G9X$LRYz)bJ2C?^9*bhr`EPE&iuQL1%Ls%<@UV@kU zZ6vKf_Gtq0UVwWefP2$!z#V$E5bVSH*1rb$-lTmPyMnk+gZRy#CJ+y?o01plJCGU?#+!+8K*64b5B~qQ%HrgM;$?VbhaNj5#G&6M)15f< zrN93D;X^_k`uXT|{lyEvJN&NYvoHKX z_@m$TAHMUOk6m1jzi8we{>`QDcI4>DS))x<7vUXJ0e)UBCLqFSu5n`p~O?<`auw{QrE@@BWkZ*B+Ssxi9>!H+<{Y zzoq-9-}X)a>G$9KO-sLV>A(E^Z(LZq_@__Kf9=L1;&1=U|9bL`m;d269XNt)Ay>Q`@(o|}+rJt8 z_9K7xXFvSd?>+GPube%I7aIpoy#AAa^1*NUfw%nrUu=Buub=z6kAB(w5j}}%kU@Pl zE_lcceDMG0uskH?60UE`YYLh8C zml3o=V(K9wDiCuAg*fz{eGqA4Xg>rmJ1<`a=>y9Zi7Ev7kcvbU^aecsEaYB&BYu50 zzTT_~97Qu81>BGbr{iF+72@c_?Z8ii8Y@Uch=7TD&2vwly+-tol_Kc)A<;NK+JA`u z;X1=Pv8VP40}ad3eQ4-4%^>R5Hrm^rT6ZH^t+kq4?>~g+ww-31Zhf+;S)EM2W^D_=84n4v8d_a zaEI#O7^nUX1D^g351Rh{rTg%k{K~Y@V1dEx$RT$U4hwN;?S*#ufDmt}lKI(wVEupX z*~?dNp1W{);rjX7rE9f?Rtu05vhUjXKDY6=J)nKO{P|QH$9iZWAKw2b7Hq*jrB4O& z18(EhgFpCbZTw)q@eh8gjlbEQ&^THSF{Io418^10 zVcRVZAzlfK6}%Tmlv4qcsD(hI$DuSm4yCE}xDbav^cvF5C{T$MCF+X8<8mOUnV*GC zfDCO9J6nA4|Ksd3qv$cMKY$U{Chm)b5MKoM$ziVYmxWj=gBh?{B&|I!1DJ$%0GfDrG4?-4ef96mPJj+=g4ZKx1HBX7yM_r=YFeu&i2Ll~{a zXnxuBFB|f>`Q!M2f&_kpfyQqX%Y*!U9{EHzjJ`%;4w<4X5hx_j-(f^lb#Y}zqB$u( zBO(X&G&}>lx1yT@uV_YIXJu0noKu=c5Zn%$y(~~&HN0E5=DL2826EZczn+&g^~2sh z0%qVcV0k0+@{U~gR#v=uxy(Qo0C=AIGJRVpGy=4R4}@BLW|0Cj6;x~Ms#F)Qx_f{45wOG>FPm^W|8<`%!Mt5lOE(rLuai`l3vfwDjcjT}H zLk_}hVU4FT^eyY*x*CntNTxOiu{o4j&F55bH)2L%Vsi#Fj+jl(Ckf;O_cNZwaeI6% z$eJ6n*KNmstFaTLvX`_Q!&P=V+@!}hlQsm+xaTf|Bzm|TOtk@B_R=6}MHH6X?1zUa)Qqtng-UrYFR3ESqVYk4{3NXkX1sPQyuG;EW^WnNA zEFn*Ax3uqk_@Gu|A9j`430I44eb+}wi+%o+A0aIkN;ljZUtO-k9)t=z0Uh=`57?D2 z=|xZ`o(>XuYmU|i!wT5RK(nEtZUspi#?gxOhCK|>D0r%Yvm1UC1#L)g){Sk$sAr#F z!^(NKmu7K?n}IZU9x9bnO08pK4UlRvs7^3;?Mpw&4B)bg!YfiQ9o0!%2TbYnQOjv+ zD&N$VUWZ>sy^gF-=U-kAvR;Bg96@X0njF40*A60Cz0&Kf$cC)5rc7f&LtfpxLq!!X zf)r48!{#Q#I9#QJ3s0c_h*WJYWy#9QyexJBsEd6tJh>*(6dL!FY~_v&+G&8*O3^Qk zoTs-+z@Sy4Qzp?udsL+E6uNWd@LWPTkX3^V8ll~s;RYucix8OEK7UV``-6Ht%mj;Xe<2UsS#2h}jiU-f#S!x~VE71M*GBApu_PvUfpY_?-b zFK0t&1#4HgqacwUy#|@smM(-znqBX)q$4(4Fwcx&md5Grc8x{Pd8NBikB{j-NGLoN z>^$wad%;o`C(y%DQE$Z-Iybwmv)3}JxYCev{^j%uHGeykgGJlRS!R!zJFk9PukY+7=G2s@qM`cHQw@zbE;nFc77VbxE=CPWSoCyXPx9mpg=BNUJ1^dkMJrR*eOCRcZ`hg=U5 zvYd>`MSnApX)g(6aNBQY?H!qIgsF_9AlJsQr^e`w$S{@ZM!X%3soBj93FzdZ=nC?d zYp=rb%s5h`MG^UV=RLJt7w3qLJKZGi;(S^I&5k<2D-)6Pq~Qe<(`#!@zcsU3uTRdL zoSLZDPc(ghddi=eobV?nTc?8AllA)A^xEodbM4g3H0LZS zE~jAM;{L5`XoZLNGbyRe>eFwX3)ely9X|Qjh=@RwymxnAFI~8Ct+q;$L0-x0Gn?J> z@Z;3{s8#EATN*6dRHB{y#**eKh9qf}TK2T{K$~}D)!|ZIgX3UQVt37l)g{t8>6!X{ zCD@iL+P;Y^hq8>6+9%JdH}VL_fFJt9k0+fZCdU2D=% zJ5|P0RSQLp6xd~*{m`(NrwiCU22NLHEM1PwNTV84qRSz0hjSKC8>o}&yIfV+W3hb`#8#4%ZVQcyeEb%VK}bM3PTAu zGp7>Qmb}d~vz~G-3Ho@sUs&9@SUVGE!@3bAguc);UQ<~~M}!>OT!$1!D=HjS3omSx1;XG(M2WsKMtz4snFnxsu= zLr>%2^>Xsg<>(l6lOW0(aGq&6z&JTsvL^>xf3-_+%G{E?tej^@DKeGiip$f?zk-k5YAa20Ggja!QAaN`6s*Rc<%j-;KbYg)%nmCWT> zW#_B3WX@N+aXW18%vW1+l+}{p{k<>=YTY2|ga}uO()nuJCym=rvY<7O4Qs6#_o8gR z$}=@z4Wli;9k%AHYIf$UWB6+<3T|igqZRo0+h2`)M27Rj!B$(2Oa8AFqn;nN8u{nS z%}SlY_{amCZ^eajw2Zi#!_$6yo|f$fb-=ykLbG9Ui+Y_^+w925h$`6E9B`a#?;US_ zYdMviE_*yOKU_PlH2{#N!qP}-mzESXJZX^e;Or|6P3^QiW~q#{CubPz<7Bhw1ZnE8 z2aVw|i8ZonqLkNS*^nAA402>-WFF3JOimfnz@+5TZu~Wq(C~{=5uY3$lLbLRqkJd6 zM@HsnfaQ7PUQz@$GBR@HFqu9+d`O!<-l9z(=i==M_5j&jxOP01*HnbBYy9}lKl~Ch zeq8(P50mi&Q5P_N43!%{UO%8om_PO%IwqeebuydJ6PUIaNIw|(c|nz-aI!4il-J{4 z79>}f)NH3xnljH00Owh!%x)j*YcDWMZ7W$1vyI*=g>$CCs-I?|A5Bb+cM$uQg_|{; zqzRHZRS|h9nSL;$r67~OY=ueC%;IE6!k>WM=2qB(wnN8ySY)+i+Vz_ODlN2H(wCjE znZ!%yWYbSt29WJ=GaS?15 zitZ#iJ;ODr$2m&gS(e%|i)92mK)5D*DKK)p*IiHiR!~EL`f;@!9XUK6Mp=-o`ORQ_ zJ6sEO_&RMdRR}v9M5+K#x51q>&;!Cc&}6OSN8=qo^4Ejpo@yV{OH1l^f|_!6uz!NL z0oH7*P1zbU+Ch;#XPbnoEN?kV14&3v(~-Br!3XkO0Njk`NE*3{Ko`1&Q1alb{`>DcN~W)Gt2y z0cj>Am3~5G+l8k^omESNuAlf>AU$0brY1USFeYzoz!DUu1c-t%wY2h zqsH^n^OH`_9_`@W}nq^K#WD*P0#Jf+HfJW_Sk^krMrr;!peE__Gp;( z`U1=En7kTEUryJjN8xIM{npQD_0jn2_&dr86{Z=X5NlJ~4VvLv7_@REebj?$PWWPL z4QV28d|YcHk7!L~VG)_hdRU9xOi9e`1)Qlf|O@23( z<7-wd=cKNHm#l1SU3E_XP3H<}P1Li9+B@A$vVM)KXXEZp60UD#a=1AnC+qc@+GKt5 z1aIRc2fDvYyG~BCn+NrjP)Uuz8P$Rna%VPIq!nz1&7cMv9A$dscCh$|u&O9M+mBl5 zoO*==hCEbyq@5UWGw-$^b$1rDv0EXxq|~vS$MTy`DpCkmJ!Y(9Y?5N+-o>AEtY}{> zS|q3^W%%S4>B)T?CaQhF8S^MLd@m+a+GrBS;gX}(GQ*xS^4pk>fkV?IsK%w~`Mw8b zL{ZLNr+Yz=owo;rFOg?q2MI5VLiGTflQSEx#TSolw1zWr1)?!JBO5SpY=o&|$~E7F zBImrLdm^hNhdFA&HNGm4j2WfaBN=Q5^~Eo_xrKK79BYfFt+PRr;Us<>5k8DV$*qPm zCKgP4rL0d*HO{4sV@!TpJV_A5PWwyhP!uGBW5vU4L)}U#RELe?BtMQ04-Z!Xn66km z?d4sSe$?EElhhkgF48m$TI3}~c$N9wr4jOXdL!~h>CxhQ-wiaR=eOJ5huF<498_vF{QEWeHLy{VgpJu5zTD#hA5$6wkg?cs2sa<)S?YOx~{Dm|La%I5F zEW`;AyBN_7mB?mZwp{@FJ&i?(w3plLM3lf~RlfkfH!tlYazROV!=MPCgOPwWwMH8h z_4#}A+fjRVL|Z$-8!tck+C!|fHRQa*`k_kUkY93DavX0j zDMVDw{KOf9y2{n!&K{d%3h5%?vdKmCktFSF#*lM=ePuasR5kQ4>;f%~s>V+W3r!6| zqCr1vckaYy=x#8$G(buli&O2A0^);PJZ_VW+Ri6+W_o^ z#b+=Ze(N61hHhIh@34%}b2F#48-`ZBMY%px;mN(33ZLN3r8d13DX??_4DVd9+FMte{hY0H4M)HE9mn7w)3Ul)iH*f<0&gk|q9F*d;i_%t z>Q;~>VGBpM3|Z2CYNQ_=9K1k3SF;U-XYzU{hvAPMm6Wt)l!Paoeu+$bT|{q>$fh4* zrg|w%@u}Pn+HLYvU6L($P&1hXyl%IYA2n!h#IlA8vgP1`yp)08lEd1=m88wFU^`Aa zW36BucZ!UkJAdZp#j%a7(>_L3YaCEIf)2Gz{_r?Qjbb?Nt z?68+qS^Bht|0er+b4L=CC$8Mv0=cRiIY+mjNYC6nf|vF+MJZnlq9F0xH)3^;!C36Q zd3)HvEqS)dbtSbO^V3$#f9~APo4Put&OX}^t)$IMmuqL+a05B>gFF8NJ0@?YaO{M{G8wi~ISdM=e(>kf z5da$}bR?5@TIra)2q;qNx7+bHnxeX7@nKI%D$}sjYiE8G#J#k=GuDrDMpSx3^-fxu zgCZz8MI`dGnTg5i=~I)Z>L>ZZME%ss*%PNuO_DPf%h)kgotd1SJ~?x8YMQW7-oF}# zH|)3DBZRafRsp43>V=KC6TA?wt%c2iYS@O|AX~^2(v8))NK`PmdOpw{1A8N0UvFDl zXoac2+74v8(^-w%DJI<|Ga7j7bVGi&HLRK?v8RzvYK*q804Nnn~biL8?GUNCpBN z#{IP{K#UDpIfujbC{BV@KDQPp&47{d9C3L5gOH$H8E`qM3jh16#{E&9{Z=CG6S>aaSD& z0p*S0R5{L?OYd5cZu-d#$!#K~3pcK*p5)Vh5@HHc3nRmD-H%#v=NzTDsXL1yzqM!L zy>yLI5%NW2_KY7Nrq8iit}4!pR4=uHC<`;J*?A0b`*bj#PLPdtqF!^1sX8DlO0mXL z5Vg*Pk)IgNF5e>FpXb~Y1?j?I;l0&=!}Y0(3>iH9afUohDy*+KbSg|`I7gEf8Rz*%L)A>NmVWE>x)eldn1x#i zBU-}-i;N|qPRiT|ILf>AX;K-<#op+Z)79m$8ANHIO7ohHXo<5=ULWPnUmCW92*>x* z&9FOCY){vBwdtj$C*@PYPCuCG1|GZJJND}V0HegfDw?;7P*Ej%*|ORlhF)9bAix2g zp~#{i1t$%g=WgVR(5425grRF68;W4C_hU%f^y$ZPfWQZnyAAGXTXU8#^DZGJdopo0RQA zZ&CqJ$;W!yc&pKGujegBjV+6{cq>TS{*EVCM&T;HuQp%w-doz}^72?~e2l^>DchTl z{8KtXSw^*faMiK68yC5Yr~M=)VDCQALQQtwnPhA@vQkK`!h_elH-$e$wy2GciRaTE zK#eWe@HoJ3Nx?CUbDmK%zj^XmY%DLlc=!oEpVG-~o8u4qMrV?D)xMkjQ1v0lFOLbnJ#sW*w7hxQ;lq?SNzt zc7r?0{9)H+woB;+e0u{+tqx&;xs2Z*)n|8MI94{_nR>mGY9ry}++yCs_Pf8WLkb`7 zGaQ2EU9;i7fB7|JHk@4iDl!`)NhHjM``!4$BRTsFjE4CqFd07g+k1;NR9p)IN1R67ug#BTHqt*m%0<6y84zsIInYBmx8yF(8k{2Sg%%+r1`(5uv z?~YexbqRMqpg8f8GS{qyw{gyz9>INDRSz(u+@bc~9Wz|D7T&%GIrySy6G;|$1ctUj zA!@c0F2NCM<|)aHK7hT;7d(cy$c~>%SCn!P0fQQ8Ov|8*yww&{3ngMptN4nqnn8#K zonua6YSgNFOs<~q_bWPa9jvES?^Nf0TAjwNQ>3ojeFsD|9gauZ>zU2V7e zP+EGJTf^s=Qk>ym3^IPvhwJlc)9(fs;^ca;e*U&o1uHK(;GJh@+kqcp+lP~H#ph~$ z)qtGc@R9Q?NUjInw%^2P`(7>f+F96byO5p_;XbZaQ;BbuzErv*@v z)5XOk0J-bZHvNk8aB<;1?q8P>Ri-OE+3WZbmN?j}xM}K+XwVS*r3O!+;KT>x+?>$ zWZGlnbnP1Qp@@+0zZ*}%?2eQa;?$VJc2{=%+l?6t;o)@A*#DxRQe?nq!jPr9b(zI;1#oS| zjf88*90y_TXLs}{v?#o)B#gsVu39_osWGW8N`X|}sLINKqnpB!E1h!60gW|-Yn$uR z>qRR31csRbcp&irn?3B&3L%Im<4CvS6p=R!c}}w)bunzV0{KZB=Ug{yae`!KLNTQf4+ZQ-EV5XOgwdmMPf3Nve ztG=tE_eE%HX__k~ho8S=0wtOJi|@TOpk>pWd*0g&cDy+cCnm_3Ouz5Un-+BXN0n7~ zK!bNiRJl@$9nKE}`PzalwS)0S!q=nLe$9%P#O1cXi&jYNy1oh@+L8g*L1Y+%;n^dc|H}6UzbGBROUGPTkzXv6nY)3{slv@h! z9XmW}svmD&-pa2Cd_~2*VTYTvFgqf;4at@DVMg;lNnM?^)MX?Rw|stE8Fis`=61A3 zBQQKvvL6O7Dzon`SuGZz0}~`{a;vHe3uhqmQ1rE+V~q_ET5q7OA-cD_Wn-w~Wz~6u z4I&@);aCQp!lj_Dk#2IY+6&~DSg$HwJ!ghO#-T~zE_GZ2EBHS z2{|D0`l~aryfH&@NWRy6k6-k_JSLs(q^|hq_ZLywK`z` zi{$yXs4IVTS=gmrIOK3uS5zl;TXa}RD_K+_KVUVsd`+cJ>{6|eFkL75&WleZ`?q=7 zfgu2_`qv%j6TJ^=NK#60gHFCO1}#D#(q`(MExInJ=m@EI_Q~rW9O%23x_#<|QkaOc z&@?anycHzT!Nh@A=${7Tye(UVIgJDv!0ifL#Z56~^P|7Ikw07EqC0uLSZfR>3 z?5mO}bD^F>r;ohNu&-uH2E`iZk8`T?Vofr}NQ%D7%7#~43zN>apBTb3i#^ph(xk7x z&dpR(pEX}rFUSedFqv#fq0GNQMjdxep^uj8077|x?e?(D{b0_d(#Ksi^{1>!?WZcX zs0e>$UMYI{_B1ooQbexn!g9rO*OYT6Ux$?dDBVn9mUR*G+}kpCCI=L-Q>6=_6GIEO zzGhr4D@_sGLN#v=&OxiE6&DyZOujl(WKC)C=txZ`05*5kDlr}uH-7daF!8SZnA6?J4B2jiq3fhs?)hIYG|*$GthbF6mlI?@2#tVab>)V#LKGWCn@FIokTWY*UWTVr8rxrml7;Q@(|} zbxZt)`7_Hjs+kEWpE?w_%-26_xJhQLPzsaFDB5fLE(`bd(MKAwF)nSP6qsQ_dH+!A~!Esm7L6dg$anCu*Y@m^{P@zwu zrE%re^M0k(Hdr>i3tBnuQ-Awqz5A)li&w5*``qhGH*P-t%zHlX^ZnIkD_C3K2;aBa?nH6-{Yjej zwzhBYe4sutIW;|V;^e7W&bh;QQHCfdtPZ|DjLCUqhr-)W6)Q*J0d#wXoodeU`?4Cs z=vP6s@CWPPMQdA5X2Q|eE<9+S4*Yyz(LX_W-Uf6Q!WY_j{sgTCPR->fF6}1WDeWfk{iO9Lk+VOe_ z{fI(Rm4y_$0L1eZHVaY{KBm&TSnW*ePzB?XW$&v>kl^OmtLDn^1yewj-FV~+XzQmU zmP-+G^Hf##9VVd5Sd-;&T|VK^_$2eIRl+}8N;Vv<su&jDy%^? zdi=E{z+vxxiZ&(aaxX}*IljXe;8M?~1P{s?kiL!40&Pa*xW^&H^khOZ_m#oLeoz?* zXK$C2O8!zVuc`ukOnSA`thW)M>?mUX;ql+t=>}JEIgY02Do;#qb8$I{0FF{q%1S5% zVnuTi%0w!wsuu;UYMb1H>J75t;m}CV5Mo&TsbFW65gkSi)xDi7Wk^uBHDaOS>l^#m z30i6L0Ky+8t4{?x29-}Blbcp6t%}14C=xwGrDx#@ng#8RBQzHbCxtPmS&|#^y$q!v z+3f)99VSa7T7#mEk7kx{Np(dg&-Spl3_v(5lo$2-4N^*A&~?=gF)9|+G@;t@bow@Y zwD2;i_LM5u4+8J;;P(8~KtMZS4$X)L1_erP7LKAfr8DNOa5Q91OuJE4AJwyKm7W_r zg3!_Y(k&nx$I+usst$@CdNRwp6g8vyOv#Hyze&QPe1Ugjgp6XGm&56z-=sr@?VW{I zCyc^03la*2v*OTkiy0}JORs=q(;dIL6-2E#N$K_g4!Y0^#h`9v74U7WsORDvYO9%x9NrTo)`DUhI>pc4cGva15QNC2s*4>+pJQ#gmUw=38T)p0*G zcRu{dMxzq1Lj8nEcb1${G|T6G7+W8kzx$Hz60pczg5n^C+S!Q6@) zYip_ z>1=KZC-UAclH)96rDqzUm~mt{$kCB{2@0vY9oWEsgv9rUm-(wr9ltR_u^W?)FNu>a zuH&j;IETGEiWD6-8#Il{4)}snbRZ{#?Dk;!m6xumbTKWJo*@kqgu1KgU;<|`YUqT> z)(wdxfp5`J;1=YWsUeqZ+-i6fqH=d~rH=2yLplzNJ{(~;Qx;%n#RdBd+@nx(SX1Qv zV#d=UJ>)Xs9`2(}40z1bktQWVz@1me@1gkV{-HOsN|V?}uHXk895KZ#HaX7^#cbY{ zy4G|CkN=^`YqB(e(_-ZQ=<6=HF$AWGgS9ZrZl!BvfhD1-)mp^)fxWfWxdI-aLLIZL z*{6d9}%u(V7!A<`|a>>JT;#yfZ3lL~7xsJ4+pnNpBC;d)|!j`v|w%>&>Bh zzl5ulIJihXQJWie$FY|EeY-;%ykS(W=P8PdkdQl`v%dHb1~31rmO z_s`!#WH4MPi1eb;lXP9Z(U{LiEv74aS)i*cy$-)5qMO!}$NdnPT46_{v=M#Cf;#>p?sD5LS!rdZY z5a`MaGjB@Cv&s5$9Bv=$BZs-yn#uVgPZVbkbR|G}D!?k>9&t}K=7&XHo6#HjsNgL> zW(q0IrjU~KTlpjQdP6%wM5ZxC>AK|eym&WePs~$Vna1qNdA*rx%udboO4gX2(2I_4 zZP;6$ICG2qnbcD4baetUq(hJBCkoU%6m#K{_vLt<%yAl{lF%c)cPQQdG_of^sS0y5-`ELXk!^$mnCQ@J5Ms-n%lNSdlNnalAy zGq+EN?Fp99Ji%F%l;J(MyDHtX8-iu7fZs`7kYd@iz{odKoS+=U%8Kxv&h(Cc z7nW3&v~bClEIk0K)Eoth%f(go%sG&v85S6~o(?xkQ?4aJP}^v=YIJ#{T#@gPr>0Jw zI#EBBcckui8%r~3*Yu@b#>jGS)#-W_s_St&`kYP9s;Gv{aMTJH@~B&{=*B%{Uc`9h zTH8-I_&Q3tikkpjbFLTSCIU{~9nk%G26o2+Aj zCYAwkUx{6ETMxH_NVjio|JJDEiXl*!zUXGxIdQbIPsjZ@d%hh)JW#rssu$5sCa&Z}>aT3$u9z8o-9l#Jc+i?ChH9t1vsX+Es%yt7r|IT~A4YW0v7DMi zefJxErA+tk>26|&ym6|$acsp zPjuED?l8RJ&wJ87l#;;VtQ<>$jO00Gq4<*1mFJ2$a5zV`t)-dLKHyER7I}pVC&z7_ zQpM%EP9tE;#{cl5k@s52xa3H%5+iWVxWf@@qIw z{B{H00jOgXyqdc%l)IaN$!xq4_^lwRt%X6m)fj#r`dS}8u_~;{JB~+CXCJdu4WJ;b z)CFp09Ai4n$rj~_cdu15r3)UDsxv9llwyK*jP|>#GRl6dH7HD*BUJY?Q6{dAuby~DwSc@m>9EIb~e!g@+R8@)VXOgvV!!py)9+lrKRf^*@5?-iIQt*_+trH z?Vg~7>U0dbano%QS=pkEkCqfx#lwfzD183P=uFy#)E2Ab>y&mr3&uUBVYtX}!6qNN z2|s{*$Bp-;aU_SI&#}%OSi{V8O6Ov~K@=!=qd|PsTF94$Q&^U13Rk@MYuxx$S^gAA znm;8TQ-k?_qIVa&+|J`uCwuR>Rr$*)LaS!rznrGRGLh1p@^$PMDY=^t^ZcGav08>B z5|n#VK6X)!iW+bZ@a5|ioZ7(9nJ1)}< zm%;QRqgLD5=;uz>9(9IPbfy9i9Z~0Q5RkC$?n5#|m(Hb!si{MNVXeMx_l;L)lOsJ%i)f)!C%?uwL=P-O)haf z@&r~0Y64{D8sD90D!2mf?lNJ$CYMi*8Z8MbQM02oA&7gTXFd#XDVpc-O0bP>H~Yer zBSq>UP7;JUrQ3-j&v8KM88T3$x~;N27^**6lvR|AdVH=s9vh!nNL5zT!BtDP0NQ$; zYqd`!&AnAA)@(O6v@KUIFANm+`Zt-mI$C$q=LB*uiwVAv#mho5D36yd(U+^szEV?f zZ(X9Mo%N4+vp9$L=Iq@gyavb~cWdJaM-|pJDl-moQ5k&n?j^tWFac0Btfq4<$&Iq4 z)n0S0C$i!emnSD4zE5_#%dFkvFSJOzkAiJ|krdl-7!DhUQRvrP*QhgQ$JqV zTrZ!o80XxuPSCxgmQ`t%l)6TEp&4U_?mO#whVJ^%`=dSv=33VSA`5-I~ z)nPGK_$;27W)W>@r&?g{oGSyRj5Wp-bTj$nLZK8G2x=LyCEN&_n`y6;jzJ$M4XP+V z)OJvz&YfE2HNqZ-Bmk|6xMcU(o%^!P2yOMnbKeM-kT?N zH|e?|4Q^2xDf4_xDu(KjNv}|gQ{KsHzvwj=Z?c6?F_@!WD|%a^tR7baBw0}ut94&< zn{x5wjlQnZ8L+E+u(`u$qkyOm>mNU@`r*(;i=Hq|Xly9+@KqF5w;|2!TBeW)wF)AxN3>E9cTLaYnf9!ou6DHrV%Tl@{6G^t8jyO-&!x> zL%eA<>BmxT+jF^ z-3jTs<_qI;2(WLxc4U}o(%wG0OQShj?Q53RfB}um;i`suOdrH#$!LT$a>$biH?X+O zHURHNt#Ij6#rCm-nnBEKEBvz=EBeo^;?mBCXwZb07;SgC()h9%a0HqQL^p<^iZi zaB|WNs~rqm-Z;ysoUTvzt*52uRq!#arBPTSCxOL+=Cqrn%vpWtDm9F{)$4S2#&GsA z#uZX3BLF2Kd1pZy7St|fxm1uj_}KfP%;L4{qW4$2a*>IojdOzI8OCWxwIK}b+TI~j^nJBG_b}T$MGAbgBF(}hajAvgKYPjI9=Oy)pAtH z{?=s^XHC5lD{%W3)qz4Q5BXgo9a8{RnA{k5|?2<0DdQ z%hqqO+n95sC3kZWIp(JU3b4_D*%X4S5ugFUBIlCJu(v!prFWrL(S|xbiSL|q)(~rq>r;6$~)#LC+Sc|$Y|T< z`+H#$w60%W8Wiv~P?(tO+q7kVl;jD5!BpN=tN!a9UD242xE6Q6Vhdbdl3snRj;$Pd z*amOuEJ@^KJ4qpu;bjEQ#sC)SeFMqI0`n&a*_iZ3<@QDh371mnWhcnw>JILShuJI5 z{5GqMV*{jA>ExMtE6mQhMIfofSaGDG0XT2nF zl5FT%JhxcbSZM9aB;>Nz@!ILCY6y0`hV*dThKheIFEwxnPqN2>x@vxpB6NzNwWQ~4 z9V~vG2nJi*J&vaN#AWACmAupq^{q1ULcaO18Pw?N^EDnr%EHWg+|4-oIK#-j5|RpTJP)wR`fo= zGCaBM-HkKbZW_`nTn9+og&b76F;^jW>meiB-fHpDCetA*;-cXfI&o`cd@O&k2_F?3 z;5gxO=10ZUIcE($qc0wE&V|=+NVY48b!BoDkdbmz>*F9y-iSM0(>G38{ixjTmnRna zJgy`*KVT%Si)W&03FL4q#&FwL(lmPG9oU3Ytmar?`7Di930zI1q|4=^?_Cpznh;cZ6rmrkRv}B;$4~ zNOa%YlB0-+sidztZH%j3j@QrfMQQZP zU8-^g%9bltx=*qfEB5mM^;Nh}n;y~!yBeGYpmW~Qx`we}Z-kX`H!2{kKvJ{F$2=yz z$gv@+>44VCJGFahEv5U`oHgjEO)J1Gl*6T+Ei)UX7qi z+@a*4x82)CW1-t^Qx2MrnO~4k9|{%88&LC|4rW8L#VSTLm2*s}jr|t7`$o=S?nEc{ z@&`Mq3O}0LSg5&~Q1uyh9LpTED#VeZH6)zCnR!V3Fw#o}1iw{Gyxo=pZ&csKT3CQO z{*H`-poOcMIe;sSBXpB%`dS-{lf(@a!8R@UJ-R?mEwVLU)N1iokhJ}sQP{U5nFKW~ z|lk1-YIl0Ha^QFgJX^t!!tqZ>w^q)Xc2-(;vmQN@?yR8712YqxPkdB=j1m;%U*+YRmcCVRkj* z`+sHC`3uGyXpp&c^nHP%W&zYnj^AzvrHM?GnpBJ()s`yW7dcUOxiji)*3ePN!yZnf z)#xJAIk^~aCUF*Sj?+x(YZYpz&HX?mV~Q{Pu3<+3C3;l8do`9Z>5a3Oa~N*pbZ&gy z?;v;K*p}al)3KyCJ}*0d7>!R&Pt1-_1;NDZ$y4DT zZxy$yg4g^k3zEpO7UY7pp-*s@bYqIUY~LR!i~ z`*a_{idmxy+KMSmZS}!oa*b+OsGMG3AQyNL#^}y}T5~)9tzaM}O`F>JjRx!vtaV+GEtu_EH zHnWdL{S6&kHD~;3H#*%3%Ibv7B5#)y^*WkIvn3@b<#3fMjH94af`Gfx=}yYiz*#+y z5UMnZ^+o|QCaY({$Zmr)(V2qYm?MPrvZe+@0BAf?pDV-(q&?8f6X{SO^hA9~aj0SpyVV<75l^;JIWHaHg_P)Q|`6Q_h2r z)g7s|$cSyFr8W$bnABYp>eXOTUeCXcqSFcQ@X@t+JgS<(g=vP6LA}?sq;}h5ejy;e zn&&FO+YyTkdlq)vXMt!!B@$z{o=(W<*sH8qxHzB0ENT?=3?Hs zGkNQUv~Qrho&@8C3B(95$9ueMf0h%2fNif;4gvWR#UD2Pk++o`^Uo28uH3n?Qs!38?D?Gxd$B%`-= ziTg+z(xbDw&T8Z7yHq@>B8%Yj#crG<<*7Eseg?P0EKnhY)Nx@gEcAbL7@LzgkuOT` zy~8iSY48I3v^ag*u->jwsS#RRRZ{%iBDWYu;W~IYA&{L z*}A-i(+Bva6%75B_?X_}SMhBtUR!gn>GkTP)1xz^Cr3|>PSo`cqPnTYMJygVWg&Mv zT%{&zrzc13@2QbOH&l_jA?0&%(Yz-T;HF-r)X3vw_=nr*4bAe02)Ym6lcN(8qZ6Z3 zqtl}&47~VIaqf3mC1Uh$-}a+m)la&Kztf9)?cRFOZD#RS&|J83{>;MlYu6V(@8*@8 zmv3G?f9>pzt52Ul>+Ny4vNi!RIH@%lf`G=hczR;eVfIBiTwTP$qg2sEerjq=!cE*G`!x=tYWZJbCmMO)YWjBjq%vaWPXWfpEg=YYURu5~*$TZC2= zSnRUqq1W-;nrvX5guQNpk}HEGXPG43O?46=;kZ#GOY&JLJ=~^(a2%mJp?Z~p>G-!B z6LqTKs(@-`GB=si5`Ihd<($icU)V_*0d1miPQ!s*-aD-Q)?=j%G5BhrG#d)JYFuxZ zQ}73Wf|3=tA);Xrc@mqg*~SWDHTN{l(ZD> z9h0Uh*#8X-OcG30Id?1byFNppn%vdt---Fa!fw#8qswuzmP4XwNXZk+LMltny>rl~ zNI`318`m?8S&5sY9!2U9wW=dqFh@VS;HQ&-paV1gsMZYuAxo{E3=X(2Es<{Kw5U=N zLq$bh_-U13Lta2p31tyuf@$0`Gh5V7vVH` zX~(FFVv8i;?!vuv6U1U_aq~u}yOtUTFj_=$h0u%3jZXIhC0%WW>887)rtLUuWYic8 z@#?3N>S}#4rn(EfqDX{rp19fGhu~TguubMTCShmI33CT%D{v;ppp8k?VvR( zgUDZP7ms~%hx96t+$Z4^ADUfKmGd*~ytCwOyFZ%*K85H3OEO*~lrTV!vy>MvkKkl` zwjAIaXAqG_q8!cCM6KiBt|22B?2CHimh&NHapt#couCsZxSL>HPT7q^Ztc&*#Qei- z=At|2dEaHoB|M}X(`dE&g2B0dWpqI1G$^o&fr`p2Jywbit*-O{X-Hj)DR0-#qO;&H z`kQoOPRl&C%%ItvxWIov2cP>Y3v+IQDkyNh%N0h4fWMy^zGK&Gf7M~U`@ONACiIT|d^mlEhS zYCc^{H&?mZ0uM>!&XVC>#QMT}NMtgZO(1ko@3ytJN-6uzU&z~|FUDQGbR}2$9eb>- z?x2OG&TnSH|9|scnGxy>77OaxQbs8nO4NH^)Ks+#2)eX|jPW~H=ozF~wuOv6Q5PbA zfllv5Ld9*}$`&)z3>=e>-G&x@(`pF0#;^&6ieB`&C|It=lx2pEx~26sF+)W5n{SOH zN!6{x+lO^{%zy!8=oNulQALYY;iydco?7Jr>bCtRBYcI9N6}+d+xVctYZ_0kU75?F zW2>0wl%OI35JTHZGe%^k=oIOP@S-P!rNN8R8y{Dqk4DOm-FtpC@$nlJm)^K1SDX!& z!HbfsBvo_GYDgXNI|0ZEKlE~Cmlln0OqH~rvAcCrA5d2TuZ0xa&7s|~ZyToLHNi0@ z(Atso0@?!5G~lcYUxMsvXr`OVLbp@7KDEKh_NeC30>d+?0pU0gOgkXy527g8$*U7! ztNI9PKngG&mNy1tnc_}i$eEWWEMztHad?Ho=+{X>EtZ#p=X-WNt>Pu zcFZNpginGWl-cJ zeN2zJmNB(_Cs)HGW@SB(u*m)4DdCRxH*R@SgZeA5X~!smSY{x`f$`dDfH9(O0aFW+ z4RbFk%a@T^Ab1wFVB%JpxT&%}lBdsNnt4zYuOii4-=J9*G->crP=|O5D#0^;LRWn| zC5%2WKqQrJt<^&nAb%si((70Ob`&U6kic=byxe+Xd3g-~4G;V6?uP%uYLNLaB+VC= zm&Zo%{Dr>zkgWdeSnaOF>eRl$kvfQ?^j+PpS>YA3i%KsGg{liaGz0}R4CS{9Z|!!o z>o+(3^QxBJG!&EYK89AhUb} zo^HBS%G0NsJn8ZAS$4;|9$U30N$kx_k0>8MK>YYWX?nRW z-`;wwUXsJ;Z4AF~irHjLfwWuOY zlQ2GFb7B%&c9{+)LA%5Oe-1zMxz)>YbF;|JDj|*KXHtG$hK9Lz(N}5q%00#=@M^LS zc3x?6yUR5Syf(-3iZlMccr|A`r!)>GAF$Tr zc;pPmjj*{HWcLAyn%n|cs-0hPB%SF;*$#m%~>^Beaf?0f^HJ$$jET zV@Bt^WRa+c+pn2}$kevC6sJhvsoxweZ`9S^3+OFsfQ+1lR_p#TyFkG{4s&Q-`>vQ( zMl;}mv7%Ql1(vdd!Gf|IS?Z-(t&)R_)=tBkH6p7EExx3ZRzD71ov3%LFNkE&-P>tU zO9LmAQ122kMHK}1k7=%dKbY1ue5o~hA7rfNX;*|?YK;IN3}SvZ_cAY+%wA>CoG3!> zLn@gMdtDxuB5KRjkmdRuowI4BO^z zTdcwQWj$pARdvB?c8jN$u)bg_g;E%(OsF)oZs~4yLFey6C{|1DxKtbDtI5Z?*u9cE z3{aF=3~SXa*Sf8}L31V6;JE3l8IUl=DgG#ooIH2C1HrVxi<*VwG?J&40O;~XDXJFZ zB#;>?0IAG2{7A#2U{)E-fH2e%pEEqU@t9O z?s1&>N~ZMlb(;AJ;_W-cUSO*@YPyGD3w9+-Gw(1&H6lGavy3fQOUAuSZu^|65Jx)@ zG|vYJ!Ibu@K0QJ$!?b6(c-sr9v?U=SW{C=-mV3^cZ-=S&J;o(IXB`1({Aoq{ozY=s%^F{76C z!(9BTe#m{L=Wl0;&!t&9s^@Z8EzzF8>Nk6-*YK7v)R$*3EH9i~UQmZ@C9FSw(y7rQ z5EMB-xqRxv@|n60T7sV@-lpr%)$4_`%co8jUiZ4r%M<2h({Be+%TH|Ivs25bW}Np) ztA_Br+G>2;DRgrA)RZl>;U`&5C0v4i!3+eA%@)e3Y#V*$PT6wpxYttP&YoI6HDTW* zaf(o@L}Oz1-14cj=5^pF*@o@?)Y;`z=giBsFbV9t+3Dp4JIu9q-0kkv5HRKxnOr_& zXJI{HES;ZRo?Td;wWHcVuNvA}x7CeseWSJ&w=;h|sHNe$o}bx;#Du2vgminqEF*0crcmdQgiKq)@6g!=%}Eo4T;PU`d9HCPAye z-1PF9X@fHeB?lqX%d?iQAYW^^E2ZTlo72eD@~oYdPP_`@ z>Tbl53+&YL8H*sDKqE(0cGA;kn5J<;?1RZUyL@WW^qn@7xZTcGopq{q!gjDz>-x$6 z$KIE~$8}YAUoEyJd5xWYeUhEXNjzFDS(?NoBWWZ}tSy?69cP=onR(K@XlCB{y*HAT z4brltg+f>gDWxPVfk0VG*$FAo014Yy!v2-eva~E^r%<4!_V+vIuJ6qoX=E#+-}m8w zX6C)S-*f->oO91P*M-13p;xlxBQ0~$EP(kM7D-3R zwF+}3rTG3nPg9DzJ)bj_UMMr~6b&Pt4W;y4&a%{T?z%am^u`qw8X3B|U(Pl&)AEy` zk|1lk23!@quoR+qB&kbm5C8#$iM#jlASV>l*eNdswQ+sUL@!c2{*e+3;ufAoq08DW z+J5jw_2^IIaHyl_xOa+5=%J4Np^i>v{vtOI42ZD~pm=|VzM-4@d{* zRcP}slz`&+1?|DfyBxg0*xsbH8n)Hw@XZ5#u%=1C~ZFTdi-ec`LFKKQI_uD$8zn{T=Gwma{-`yTGA%^0Ur%F*uB zS}yH~z$xXW9Ygrh)j>Zx=|>m+=%ye0=|>O!=%pWG7sG!omv;5h=l%49mfkf$e+}YC zH+|SmA9k~cv;o~wnndh*tl0guVLdcY56#m<^YqX>y)?-In&bdYa)2f|5EaPs4Ed_l zVdaO$!r%pts2uLKj+0-0y1+954X9>dpyq)5fF-3A00~RUPZuhz2I>Tlm3hFc+`-)! z(a%S|5Z%&C^ByGeGU@@YEMN$P!6^5(u;JnLVNGx`BzWUPEg0bJZh6Qpnxa}wD8lez zJ;&o0pROr14r0t1nutTdsT_6H;+}|LEEWdegWQ6lwdh5&%{6kyoUP~K(t2;yjxt>* zf5H?19PDGxa4DBt8ng-pBMpMPsEy&gw=teEk2#=Mi7yq>^s&&7c$yD{gfh8TdykJi zW}kaxdDUcMJuK@FZ&N@|_^Ux3ZpN$7mub-PO}ItbC#7LDXP`kQG(^?#^3%zJTWn9~ zOrzi;w?tiHGT1}8n^B!E8^H=W*#$_rFrB4BI%``6^NzBspBM>w`^txjBA9RN;32kL zY=<*NJnoj*MBi3I5IK!}C~2F$N0qe4O!Xd+We;rw&VpXEE_pDvLe3?FpP+dvTw~M{EQB-+%ca6P;lZ)D7SiDOG!%O+$+cszwuBB-@55$AP!N!L7pL zJ&Py7-lJ&%++r>huy`110rXyEUc>(K8paJbYh`2^EF1+Z1AD>TBw9*^j4^8#j0_G8 za{O##Lv=ZHhK?9}S{8}Y^ET+P#go7<(6Cay+zES#Zmgc%iXZ?qIMJpM(lH5vb#woA!3VNf1gEuJ4x=xMZz;c&99M)~r=W@`*|~#z zRT_rABLTx9m{MGDYpsmoZ)?EX!LFZ&KfJ zo^m&RrB0s2l7Rc(m0`sprHSEgc}cr_MF4}#*P{Ehsj6_up+Z4uCBj4x3*%GHj%eB* z7BWM$5SNBvdnK+YQYXWejI~(c7kP*qF+}%q>O(Y2FXj(#*c+cn}OTLpb)&(>NOtTM)RA@oUFB|m5S2CzfvnDSjNpeKvfVB3rPb{ey@_+ zr}?9$9M)|tgcp*WG4v+%094(Onr#JTUX~b=sH)Q1=GkoN|;HpyAV7~Nlx<%`r72Hz@L4=VrF*ub< zt+;aq(HEaLkK$)*({2`1T#FVKOxr5J{gqleXXtjDHse4%7Z$`mT3BFKc?odYXlY|i zD-B65-wFi=oyv?gosSk4mQfwi0_Y~?%-Gc8gXQ)=4dmxgDCPA4%K{Db3JY=tQ_i5p z*XkC$-N1CX!4w2+F$`E9H)Clxx1f-O0)U;zTNWUa55HDGGnBzw&}|b!b2yU05QC3_ zs3~UChM zZmAfw%s~50Cj~>LFrY6pO=Qh1vrdHjzv6}~MhbksKvY)TbYw?(ArP(t1I3l+<`&VIRp02(zyc{uDv^Bet^ym$6+(K8SJm?u8-4?!P=pv8ND=BH-tF)ULBkz5T z1c!$M>=xOU=z?J{X+!!Fl}WW>%l6iP>coZ$2v7ZGG*>=%UWyAUqKxp$$xJhudE~*) zOr@dT+62N(TF+_xwup+lw5w=Ze*K^-B7s;iX6bDZx-f`lh0Up`>Qc zq41cR)J5zx*aW2EZca$uLiwt#P37_wrv6-;2SeNum^lDvjD^9H&F}5P6zU** zQo#$Fgx^!dUh|*8*sanq@G82&l;^?##q91C8q%1DXTC`b-)^PQ?%)=F7t3x9G>l9O-+c4lhEyDlUrAF3fc32jCg^*w_n$F=eefFqS#DdtP)fI@ z^z?kGh#PbzW&(8saCeJsIr8Eb07X@HMWGyTd12xy?V{wRfGXNj`h0sHZk5mr4;a#Toco>LQ+7O_L7t8^rnMiV35g+2p`mKd{9|{DmI`sFrc5_ z_5cp(J@0uH4(JQnfY!l)em+fn1GmPSukvMl5gy%ZMrn|0JiBxtWCASlf2zmltGC0iy8*hX{+GIhP9Rj!_A^) zn)-Z7Yw7HOp~wHVgUNwlt{~&c5j6oFaoi@r-mD#plzYz}Ruel^V85rdIo&lD^(Fdy z&XwhBX*lrRkUmui=w~1Is7HXunjOmIN9)R)|^A8%hvNDu(v#Tpto;avyC~^aqXoL zD0y%_!OG(gJKHi=dfu?xObdedWlZ~^qq}-1klI#+7E-9=l(vggT3WZ~4Wnq-Da%#K zY;wbEk@R2lc}iw~#>lKbn9R1QfJtz_d0(AUKuBfiKfTd{-7 zRYj{{BT;Qv^kOlvOn8n>){7tR-B9^qcxH#@_6ZEWdo9b%`X?RBi zA+j*X$zoxSlTG>yqaEA;C2m@-*o{!^O=l>@ZdzPi3^`5?iss+T+PeJsZGuA2ZBYuX z(~BmyRWF*S+}1`Y_B^%NO?uH3ZDrpZfQp=KXx>!%NxTnbe{F>tYkfhWd|;>ixrG9oO|A z7#SPN&yIDu+2hkj|9nUHcrhM1SWigv4%^Y85uvV*uHKH$&dxf)Ox6(632o^(2imd; zT5CHxA*8Mb$iAkAyl(n6ds=>$2sgL6`bCdD^`(c8UliJwUi|oTU;6YV?|tEg8=7D8 zvNzuP$G>^;N5B7;n_qw3_5Zx{p3All{P{1pf35k>xwk%l-;J03RpP35{n4vtH`aXf z{XakB`|Zzu;1x4tZ%V%Fy2Wo5JD+Iy%b$MXi8tK-f_MM(`}$t?r5irnaKobyy!oY% ze>iXc^A!hP`>SiU=Uo2a=;yxpsz2NH_kXsy?|Hv|-%IYU>-*ZTUUX)6%RfG`Z+znk zt#IgF_K)AX|J>`}+10!EoeyL#@7;gpU*FV`H9zuCFaFGvV-w##>xHv_p^w$x_49`Y z8t;1vx$K2EzWujvoB!o)?|%61>tFSr-uWkg`|OXFW*+)qdmj5~II7<_vGW(_y!hU~ zJNp$sdecifZ@By6*9T3^1~DcsTsBI(|Ee75IU-|^WiN3I-5O)R!wdF4=H{D#4) z!;1^Y(~-#R?9!C3@5hNbOEAqU!wj?2DBi3*L$CRhZ-0B?YmeP>`L^xH_RQ^lX!p0C zzwg{zfBrZ6v;OtTr{4UFPu}_Jd*9vtPycb?{a3%p-1hCA?c?WfsQ=n||1f|4v%mP9 z&;R<@Prsyb;EwN}`PTz){PD|wbL*F<-}S;jzWPAtiC1mTKCkUBfBvETs|V|z`tD!f zzxdgoeZA21o)2~0M>fCh$dey^>xSZw-WTis;;k?K%g=_s@#VU0FL-Bt!<)X)_2!=x z|Lc*dMdRlF8=hWx^(O`vZViR%KKCD2eebnj-}|Ajq@!K~o?E2~t{_dIw z-+yS&#h-uYhAZxBX`cVq_dinm#>bN1x%OY~{Mp1qkMtk-??YF8@bb)mKl-WbAN`}( zzw)>L{Os&_=XvjZM`++Rqjx>`tzT&T%{AYz-G0e7w#;TNdr`OH68kL-h<^eIO$dJe zq<*|>Ga>iUH3u+WM+krit~S8mI+#?l1=ihG_yfzau8EM2cR?{hYvYNJ{OHr<>J1lO zQn&QsPuLgs{r7o|ksZ6YW*&X{)HgnRS$F6cKf3YZZ^S50BSdFzpv)cx-Gqy0a6?^8eh^xxgv)ZG5k*hA-i^9K!2-}kZ$P9`7R zFqwMv8!!6&p6AT8J@Axu;L{)cYWl2y&0jzF$~V00HEkQe*ZJ)G^#|LZ{_e|18eaFq zzuGkL+Iyb5a_`X#e;LdE`|R1f-v7I8>EHd$;QJ>woSQs!!S`$HcW0*E%WFpe_#e*g zdh8{CbLkI{+4(Pl zXFqk>fxq2eH`(>Zhu?Ze{tZ*#y*7Sv=ilBlJNlC+OEX)ac-_NqeZzrQKlj6L{^`wM z`9S{<7TEpLm*ti8s&Z+rEBU2Q)0?xv*+emT1BtN;6RKlt$%w|{@&(r?^*;)}Ol zb=!u=7M}e3AD{Q>Pc>ZLbMd1i`+jy&>ERza_fOx_IdgCQMI+zYbV7gMzWlK9 z;5C=^q`%y`@7rJf`TO4c+UpP8{;OBMG;-jnxBU6nzWMQ8zwO-ky{~S6YW80a+<3=g z&D*Zt*4F#VkKC30(xrF&Ztx#Qzj@E%Z>^rQ#-#?`>J1k>`y=ZTWrMB{gLzE(L48+i@(|Z z^%w8`#W!v>J~emvmv36Qb%*xURd;^qr%!*fdAk1_Kf7n|fBfpb#h3r)o|oSF^T-2d zrXK!`KJdCNzlvUa^5@68`tSSn#F6CDdAIMJ=kNH(_OJdh^Zf7p+j+b#fy&8MCo zJ}}$;inG4*;`{IY=YRUhSFdl3$MvcAJpb8)^>2IYzx{_{5JH}FR@XcGKl1TsT@vrC zyR!N4ck=)F!q2_=Lk~^-@`Za}zHt1_?>X;RU-(?+BM(1pZ+gWG`i?%(^mzLZAAkH` zzxR%-Uib9d|MtT-?fCSSpZWCIl{J6z#7_#3jdV_*c=lZL(Wn0HkAK?{xySkY7yR2` z;~(9B)uV5E_M>k&@b#Vp;}_rmts7r)>!<&6_W8f~w)?8R-^yo!+j`E@6Q8;FlP~_p z(UZsi^MdIYeKh;%uRrrwUH|a8V{gyi`MDd8-}AC(fBS8JbJxdSVD5X(mRE1v*K_Z+ zQ@4No=F4gxZSQ==tDb)RrQ@YL?|yCUxo=FLd%+Jb{ow~cM{YTAms!ink8{hwB zEqu=lzM#E!@7CQPeEg}==bv{Zeb+b6-?#G@AAKs(vKJ%roHN5euTNXd_!Mi^HqxaTdvE{BOqp5o?cv-`%et5;= z{hNRO##^^P_ivy0z=rw3{Xai4)V=%dO^46<&3^OA>B&F;*tfF>w*UCKPkrjE`%52s z+edCIoSixJ#Kl*dU+wFD)va~g?)v!quD|ZqYkqRk$6Bu2|MdeO`A`!fWHFac&(7JU zoN+Z{K5k>U2fj&X9Djb|60JEzEfglwB4_tlY|gpe}{ zA&_PZK5qhsc8WCCZH7O{wQPrP8_0>q+B2p|GuZ)uwoZ}e+O82YMLL0LCIGr8n#;;j zL{8Mes)sb2FpcdxMHr5PTjb<;gpB}v9wFmhTL^gw$>TmG9uRnH7~#}35>f-yc?Kah zC^2p$q+xg)Av*|Z+^`cU>rD7_7W}D!KOoiOpqGk;VxHHzgVhP2J8%gQkfdvXTy=Kk`pja zTsJ{g5H+;1CqdlL;L?E^){Di@!f+Bo@>^+Pkn?;PP6n;}8NS1|awlWO;q^o8JG{Pz zeFqA7Bb3V^?`N`z3^s_p|RBA>;wp$7Y~dct8kgA%yH? zX#kHdV&4IGUIzn72)PvSi9NrJ5b_1~y_FDhf_(={{v!K+Im{&ku`58A#oBo#A>r_$?EMVguI144+9#o&F?Bg$Pg%U@qnOY&RcoZ-Yn1Xk5UxP?DLfD-Q`K(mi*Am`Ejq#2fe^VXY$COtNF zOFMhD9gdJfda)SNGhiVCDbG|=@-vrP&Q{B6y2-Xmt^o!4p6ht98=Jc2Ts8d`_I%2+ z-CF>kx0C0v_X#*+3AeY)oZ-HX&fa~2k9+uII5jm2nQ&hRe==)Z1s5K5cXV`MF9ze& z!^y<-Ogs@CN={D4Mq(3j)K9X^&8!9WU`hu$HVj1vW=7N`SFt2#=$X7(xYjtX=ZiU` zEp6o?{m!B5A`>H%$;i-nY$6#QkHp5*%v~(=2Fwf@&hliKip1kbCZ~s1lV>I#ot}t{ zN7X!ite!L3kd=+Zmf`8ii9~c_C^<9jY2jroXG76)+&S9-9b@yxsgcpictWjVKTijy zp()+L(b_yU8BdH%N8`z%0Z6=q4eLH$*g=+Sb2^krhEo06WYOrzddhcO#RcqeL$T%#c1cOIr?r;&2%mv z>Ez5*JD=ubxpp86QNmfC5_qbMu>K1fn>KX`N+tA=V+DF}D=B31E{n+d4_aRRm=INbu)1h`?4 zaq*A~MVzw2nR+uD>doU|R*S|hjxm26`StkxV&*IZj)FmhT742Qt9 zwV1VBOS|1F+0<4mrRl|D&P-!uqt+&{HwtU&tT$Oj*R%>@t*NNb8DXszmJpoitBKn5 zVzIT!G3*61Z8%}ANz*v7z;{hGeP&NItu<(WfvyF^4&SG|`&_jfS}Sw*#2qS(*6Hj? zt7lKaO-PKdx?%AWyy-atx5B99%|c+IeADqKQnwYQ<6>37PRy&Nn@U)aDX&Pt`OrXX z7{dJE{!;ccv%AUgnhk84hID}jx2i@L1N->{~_R!UDTrApAZbr7~{ zNekmt>*3xQsI`7-B!+@VBW+10vlNhK#-B#=k~IYMnSz(x#LSBX7r2p{8v)x_LpWm> zWsKdmmjp0&HDuVwG9hEPC+AScE@u`>$6=2)>~_&;h4Yd!jy3CubPNecG&H!11`VPs^Bk(XchT3px8} z)Y?)$zeK|}xE5S*WEV6&1yO8~NwSTMnRcP3rB>?X<)9HiB-pDvTE3LdUarlRAo2uU ze%HbnCo!xQxu!YO&6ZLi0LwX$-^zF>Ao5IRX_;LI=rF9c0$uX`1IW(vh+|VVlt2p! z*ke0-!hIbbRc;G`a7HN_c2=+)T?Vc$<8Zb7XjKHS2mgnY3xK0sZTmN_F*2s-si?mW z$XHLVWXQMyg;;>btpkz4L(|cCA~_UEL{MS^rUjTXE{E@8G{8REZg(uy?`#)Y2PY?n zW2j0JnYnUdV|yAxLqS#BZWtO#4n_t?qsh@ps?-t5*>O>GJ=jk|;*E*%si7FEJVYXi z#~To21s>Dx2sEw-#=0uN2BnxNg*8a1|5PPE1a1_t*uwtK`*sf|Uxc()TvOq) z?z#D5SoRGCMY>wTK}$;RMw=M@0c7kA*oXor8@8fGL70MzKD35}=>gI^>rZ3PXk(DQ zO&ndM^-Kl@g>~362%J4Wg6H0k)RQYzuxmmO25gK##3uZSlnzD$0vPMt9ecr_$}wHz zQZvQ`s$@LD_zg2U-4VO%bNm1|`mt)a*Zp8|Q|2=#b%E;Xz$+y%3|0l!xTuk}^I>w`546J9V}U|G$=oKPDM!t`rhRAX4Q77cs0 zl-s8naCTL+O~(kK3+O)0DjEeI=ZsQ2ND~xf^^$8rfb_IBnn+B=wME->U8A6x1#QG? zEBp?alVE_K^@c#Ww2Ns|e!V;14 z!jdpOz>~==A7|Y%S!x(1rftirpo8;^O{+z?{2Xo1R0k{DZ1Tc6w(VSj~`IB_{ z(CI)=`Kf7I&zUJ3I=jx;Q(K(??qT{iwx=v>-Vv~~3EHmPOI`--^-M~Cd9aiY&Maj} za9NOSM#shoEgC6>0o$xRt_mbJR0R@0Qb9shAXQ|<6unVrSGVNGbPNpxE1&rrQnB5( z7UALvxS&Y~(HxmD9%Bf88v`)7S_x92|MGFu!DwuQNF#>OZgVhcRYszJ^mR)V3&Jdv zt%Zy&xg!~n>oE{SVS2cPya)@X}ljk4eh<&aS?3d^;42AA-Ka+Y9*Hp3W|`tf(80j`Nq2 z-KrrTuBWLT?p#6Q6o}R+9#Kr=tj+V!FFSB%=gBn$>@>;%?QF@~pns2R&bOztHg8l_ zz_k&8>%UeyJAG6IF1dfM09#iZ`J%g|6?Mm1wCv2YBzz4*h+1vbav;(+4J4t3WcZH5 zrtOyWoHnkfvt~hHQ95h$&6^&Euyb23?;UpyIC2eRqzhb@^sF_f7b+qbA2?JOI@YYa zsN04QrP5iOS0Teou_u}aBm}BJ4g^3n@Vl#ToIe_mj)%2YARPLHgH`bS(KKaJU+;l_ zFM|~TO@gw*lI|o9@xe0-$oX8vQ7CW>0CCQyh~u9}fjn)in@3KVZ$#(wQ#1+-kgUu? z;rAg~)ex{A64Fw0d&#leovdyf?S(nBaJ)V1=5veJ^XAC!7! z%l{&Nwu=Lx7mM_Z!p3aCH&x-lrm7g28&w>DgUC{W*)<43XIyt}^Ei(qK5L~ZuTiwk zyl$JhB?#u@m|&u|PlKraI>bFIWHiS}Lo6P_&~OF>yHIiY;@dW}(C%NdKoe|<^3}HN za8+1zeI5P#JyOl8&%HUfuo7{|WxCZfu&@!KO%)h~i0*o&lhL&rbXcL3XdXSCH5wp- z0N~HAlL%77Jvf@T9-W+-P7V$y6O)Ic6Hxt@#LUD*bc{ZL?rx?{%jveEn4uA{oPGo? zh#sjSxB8af`EIFDFmhTbRIoxIlrt+SyM)uljGw^LOBSwt&G_rBYK1mbwL-J%3RQM$ zZoV{#H!z^IfZ&ZC*Am#DeVVRibR%yS;38O8GmaN6$8ccnF6geIapNP+&DvIJE{kE3 zlv0e$oFTOkIO901a`o~OaAhhf*h&?q4Xu?2m@d?EAwemvvYCQ9`5;($$fMHUEK63t zX5@PHZL45^uV@bRXMDu{)b!1@H3I+x%n(}Lu7mcVo^bJ?fwPUUY8$w1740jw2=!vz zKDx$hF|c`=B+OtyO~S39)n`!c=BXo*WMpcJTQjTgCCgu>mIDl#1+%ajHCH~n)(vRp z>Q!|7mqzuS@G112k}+6?qC*av!Xcjk>D_L@Y zea{=u3iGK~1P0l9P@x`<(|eHE)!D#P=ol20p_F0o)2NldnaUX+yh0s`VYjt5nQ5@O z6vmdezSu_PacBrAA&i2HVnKjP!!`0nwDD@s>yB&KY8t?OGYz6nGNH%ofbUxfm)|yZwBdhH@%F*ViJ_TT zA{iMPnvTY)2MleOuxF@;@RgAG5|MapZ1PBQa5Or2C^ynOC8vdOm6^G+rO zy%G(BQ|W<7Jeq`a>gWXZykTPzWet-K4tbQeLhOAzlynxaSd=ssNsIy!@nXWPn7U4C zXeUN=JaPjxcW`EUIy#X^PDihwiN+J25$$7n8@f8^KTqSK0G12gOVnET@=@*W>^%Uv zw(y2dO-@r+9^aJjSh7lX8%5AI*cl+#E}o0IlJLEmXXYL~+iq&1gM)X%-2z$9;aR!E z6)nQkKe??_5kMLSf^Q@^DW7w0;7$yYq{>9}kfPzinc@@Woi}Ae=G~}jGj6JCGrpis zIhypymQpG}48Uu@bRnJ3>JAmnZ6k+))WN>bMJd3r=@}+igDhz`(cav`H#gQv$@cr) z8rb_b+wn{7v>9wi3sSbV@+o9U0UHkk5{~jRNiaUND*8e2kl@gRsU;vRn@mN33JK}5 z=ex5~kyw^&fwzV=h68Nl6-^Q;VF5!=g;}zfeA>&pUST0a8J*IIQB>q#wvdjm@3OLC zwL$_|#$_*+MG0yA3%D%3ZzVz=@4BTqxC&=g%ZX+U;wbvU(0Jr1#IbO>)@3Kxk4k#= zigv?mvusq5e9h^ctOV}u3&wgKuGHeu2cDqtjdKgwDI{@eMR6x{i|seC(CFKDwD=eV}(=4e1ZU`g4VTale_%nFSyl?5d}Q zRpI*Ps&M^jRn=3~X|k}MQUxn)@ z^p8h5=wngKp}tB+KD?Eb0N}A|YVzVsr75fcCEXnzeXDTf2{gpxRDx6(7Gx@csqFN4 zH^-%A#u$Jqz*w$*aCOt|A>FU6wO*;XR77j$b&xx1(IywL34(!xxSoRl=gqvH%US6V zJ$-0%thR~CsVG9s*idq6IyyEPp*|>SY_9DtacgXPg1lquXkv77VrF7sW_UO{O;JuJ zRsqRpw(Rw34$}R^w^I~?&j8)eH9;tJk=!Chi`(_I!ePqBRfR=cs=}i0s|uf1h~FH_ z>jfP=>I-gb6P3fM+84ag)3b9z<%@b2>CJW%9hh4fGo)$sxA>{2(@t3Y(lmQ9p9yPM zuqWUxi6N$CetL#UCzvainkp)yf>KMgbW7mGlFM7j883lq%S_{;m8I$QMlUL^PmQE?k5Po}PEKv$>;i7|5T?RReHb#ag3fX_|i>$s_f0<}ZMPo$TkCaNu!(>rGK}0NS}#t5Kj=qoCdD;6JL8Gz$%&EV z(17sPhG`3q_EDQjwFVSl9^IohlY;mY(2nNm=+szbFq%9PON=JRpf2gCog9r$)4e4! zHKnkxyzyLhaWPPlH{1;K0>{`i(Be%{0*{o!`d(yh7~^iN$8zCzu)zbk3YYi%+Rm;6 zsDtYa_w4WP;wi6zTaohmL3;Z$RJKJ3qP`lrBI|5$=7aNTSz>SZfqux_I2|2|#r+xO zwpfQ}wSrHVnl0H0FWbH;lS+csFX$0Pwlf6Z)XrQB1e?!CXIYzdY(Ez3l><#I;qFKNL_S#J9+MtZeu`!!8{;BNVygQ(WE35i^Sv8%J18rSO z#T)QpRlEMys&@VNshXuzl|bO~RvWyC=1pdUCMh7PZ=-_(lW z1K&D}N__C?k@&zb3j$~UY&T5+pCUm67^P`=5d{=B7PK`e-lxn=-P^QqUt8yaHVnSB z)zju@1(kM*+-P`d^JYpf=t?mg>65Cqn{8EXH(ys3UUWn&%5edzF2%D7A{IEVZKg_K zfJ}?R%||cjxh2<3JDLGDoQAUPI7P$A?9-gI4yKD>vKWb}k)6br_mbQEn zn`@1?i!uW^NQAH%7?pD&2(NjB8H)Lg` zPzkqq(>)X;F=->64qzUI23`(U1u(kpnVwvLE$_nk;M!V98adFFK(E(99acm5$+#!# zCDgtnIu;#=)88Y}0eLb@Tc_~t{?pOdF^4Sp6u>0yl;GsLj9tA{qR4`gb}ie?x3h|T z{#d;Js=#D>RbXPMU=n;P8emmRFC#5Eddke1?vk`J;y()+(B7p)Yd6pUa3P94=(SIO}e*}aCj#xmz?Y*gAz zT;0;?^18K~0OUGYJwIFHg?k*_)7EX_@(>+OT;8H#JsKt^hoZ^o#9`=Z6Kzw*))%Fu zU4wB%1e0<`yH#}C3s%N}8{|NK79z7?OlpL4!V^>wR)b**=Y&|$+E(}t*%;-kBGM|Y zt!jPmsA_#bM_u21tT5aoH-+Y2MvHJ0a0)KBMYCvU-f+R~Xim%Og-i$rv7qJ5c>|&x z&Do0VDLYnqK_hWM837Wge7VfJ4r#4?Y7g>mSj-B#d@;)+m9HyGF%WjBinWa5Z-9J3 zxdJ~q$)#T=Wnk1>&=<+(azR6`{{B;*AKwzVYi*?rQ2WlU*SVD{Wz-T-`iKR55n6-5 zZ5^~lu4T8|M$vLi*Ro}B2YRpsnktd={D7Ry#$RB-CicLq4|@gMT#${D`WGAg~?}>{;6|Xtah9JviCtIXwsY zLkate$bu(g04&fw2StckE0-~BM|e$$j#oq!k)oVQ5U(n--XewkRyF|@H~l{FgbD-- zJ-4VY(Qv5&@W75w;F`@!)Jp3_X@t=oRcU$CvsV&Wf{tJ?!Z=`y=quwZD!ETjtnEyC z>GzjwjXkz8YpoNnQAad(qM(FiWZn~-X0av515&V{jXcHGtc>%xW@&M8vCZRg3f;t3N`7EZ?FQwhp`P?tQ;^!FcBqjZB^Lew zR_m{t04a{gY6&un<^*HbIww2TRJZ=V0>NSqJ!MxDx|n z@qSeWWV@;YvQMfEm*QMg3CV(Vw!=92R=IUz&Ya7-iw6AFc-RJDvgV97Evh?9nrn%h z3P357vlg|y4&LPjy^uEcX{M{)UUFP5V;SJkYG}7xDanS>YAfR(eGlX5$3OaJ8G()( zGjc0xpfZXTn%2r`2vj#+U0w7!$F3D7ktQxv`XXj=;Nlg9u=ud3A^={Lz*+)Y{2o#g zTjX$5(9c@yJdqTSXtVxhZS_5~mgAVYb;2W6{woV-oi8~?DKA8}jr6xyV%y$IaioI8 z78qDUv0!lZ!kkfXVTHBRj>E`qq+hGTiZiRiibWMGxSC^y%Q@gKi15|vtdXAAa@L%K zG8PL7Bb*tPpffz`MAn?khNw>q)7q+sLGi(HZEu_fg3$&s)>Fx*#t7rWr15giS#n$> z&lS6LK$gJ^pqY@9&IdvUysRj*l}|y1rQYA)-|v&q0v0wUk}xA4xwtDUX=vYg<6(jC z)vFwQVbqp*CI(+2MQv>ZJkQ$ZoW5T7jLC2n9-sHKhNojAkwi2(orq5fOA`ug*gQkB z7gf5TgXyy1LAFtY#&%YifDs;?6>x+`Yz9f{zFibY;8QRiz>jcIYco5UhEI_|idrBj zLOHiHFFN=X$?Bnt5ZfP8%(E2mDN<}aVx*=MgO$>p0oOCJG*qYyjMIM^x9?Bo^m!wd z)6?@#*3fM}24TkqYh87WtHQXms=~OJs)F5unK3LOyXgf_+|P-_)9m0`w?Q_8aDKUv zYvv6&bGA~q8);X|7_O0q0L*P#B$orwOdAfy^)nrUIX=T+w4}e4N(vhOJ{re~88p9)3APUohy~td*CMJs81M20KcfZP-OWdqm$Y#~uZe zeXGwsoijz%O=tzc?15PO_(z;$p$e+6|3GIL|M-MG`nIQMe;EG&)haAiUr$dDyy$6n z)5S0)*udANjQ6!i=7T6!IuRaBp@8+Nl&~H8urAtEXCcSAY~dq48;23q=&X7+}YN(zpW=^Tb2uV zNWp|{z%*5%?%7qL?h91T@)V`exZ)N!Vp11q@cURa-7Kou%A%HGFDfFW7zZCZ;`3le zP-F=nx(W!_-O+KtXQ7A~*45R8;$K(TahSq?c|}$LBS|Gh4*@EG!;#2v)3n7BYy4uQ z2(%&kSV4%qqWXD|q;$#JdaccwZcfLD4eMg2bC{`_uAH8k99=wSPEB`auU{Hi%w2ah zde}&G-`GE8&rMG(4s`VQ9_T)HWN2zGhN9_6EHM@tNKQ{qCOo|3M%n?%I@S?zauATR zna@~GPYFC>Na2ZWx}8qFH3!qCCaworEFdYI5Brk>4N-ZOM?oA|CJJJp)qJxwBBG_U zk5JlB^z^LTRpH7xRpCm9%FR`SD}Zw0RZOGwI-3K?u}XH@&_D^K$x~hpe08}DO1r-t z=;U;~7O5O{aymDLFW1c1h>q1#jF7f3S%G2z9odR- z))*cweNkVpV63(1QVYGV?ZI1{8-^z0LJ7Z-wuQTJ)k7#xfW|FHq66_*BI-{lA+gpE zi5OcIH9>wz^qffs1Q`$rMbF0F|qbe@0e0<3qZkZZSgnpL_J?^rr zDDuV>-T%-;+~aZ!b{B#hLye%Gfvb7b5cL>O0wBk%nR5->l=0Z;Ff50i{7N~`Ncxc! z2a_>yBABI=!a|{p?qt!_Oo9c(%BYC0A+43u^uZo+m260BRf+f@kTxx_978?rWiwv^ zKzq8wJ>4jsX26;qFd4Z;`W%E>?{gL$w|~EspI6OAa+H-zOsSZ{D39DB0n~TKsd152 zafJU^c*Lw&8 zVO-!awL&((z^Qywo_p35%-YS4aA6zC>!30FTB}8(K zibsUv)&ggth>tqler{+Brc=^$<{k8a!)LW7I7>RjmEn=T4={0MZdl@o#DRf$B# zkSHLfxJjE|3toHE;K4PR zIh8PPTibY%SqSrtQF+%v0^UU6sz!hf5mV~i!SNv)Qi|Rr&w{a0+^Exw#c7sfKX)z- zx3|+qTWJwm*6;kz6ToaWK@CF#+-V)k>|te|qg=Z__RRDc1hC^aC6H2tJysjyk7UpQR0o$Z@_@yj1Eb(51|kpFVtQ&Q4`v|JOX#ij z`{?sFw$m5^?JT;9V2(Gj2M~5aXcks>?H5&h(fi}ep?56-1H&@bS36eHm)cBAHkG$I z+}YOI(bf$M1jaqkV8+8ZJMNrqIN{Fjw*87Py=ZGyuz!A4u;02C?(~CJE~lp~II&(Z zw7hQ5L(Cb?$iODT!_x56q_j*7J_Yo;6h2ZF;hrZ5ILp?H#pSTR($e+C^pfij6bYxY zj5!lYi^4Uj_(R2}Zt<*MPikdxwuUuaxVQoFtz{+3s<^FmcKNoIRWr+MS%t+6_!b~k z%^_mBY48R&;M2*sS@Blchq)A1mWJ)Xo-+7INe)U(p|XnTI91qM0pu!2H4qj_Wkw6a z`kOZhXtaVlIeh9%1<*s_==p2Q&%;@3==X8BRAyfktn%=J^P|io1U>`w5~D%j+#Fq`9bDcsT;<{Ay<^wP1?DxoHp^Rnxhsml0St{eGOS1d6+pDFv#UFdf5eG>0Dy3v z0{xU|vE4V-z_basgt8u0K#g-N%{gF#k7k#)tZ8g5GoLrp=or5aocEc+({!V(cgN6x zj7rQSZ?pG2E@Gny0tMr{d1xRxIvG#+62qOuz|}YKoq?z2dk%~yD;SJ^Py&D`Rgi8I zgzsW8!&#b&<-z{stD7q#)ClxvjYkGYV-wNjSTr&{5t|snMk|dFVn}yK2kM&3bNHIX zbI>@E=ayA)WODjYlm;JXoq({i(9yciE)1)FNrgPgL~J}dIiofY)WkSO;5PwdRL}iz zSlIyym@5xUz{Laa^lhWDbOL6OM_!}B?rE}s$>YiDc|foxmef0ca9#-QSLb9i3nmSf zD>K2P?AL=c8j=l5=PQysO4r5X802mH&_FVtn4FG`M3af5Qy81RiIZRFelCEq;lP3g zCp0tw4Ny|^@ChFJ4Hm$ZT%064xynT_C5IHkeD`>l`9E!?tCWGB=g#jei~CK=RnfwswY6^?tk#TRZR zb4I}|IqkH3^;m;G(Sx{;XUP%(PD7wx=424=+#jOx5Yk!8&UCbOw{?VybM%qZ(bm=0 z;Uk1dP!%nb^Igz$^TrbU2=|5Ha^pqIrnal}WmTNbg;hzAr434`fAqUt4L1|R0inJY zU?k102*F{(gG4S!(n+W&M$*@9da>v`Mq$%g$%Tv+ z3x^Xy9%QZlJ*qXVX3;PK2Q&~0#ePMZ4w`^N85kZi6#$og*zN;aVMkJP@!cjMR~eQ= z6QB(L^#x@K0oNcQ>^!2fvQ%t4!49pIifJuJySt6%dQS}7i7hDN24T$@jyYE_GT>ba(Q$GH zWfT@|)1}Vm$4Z91q%B(ZJO(@$tN>P#scfCb53f$|A9#=Uc-@rJXu)U|!H7npjZDd2NnG$92a5PN-dq7^m7w!kh@IGipnW?+zXaM%4Jo$UU}^Ho8&zJ;>@gp zUk%_zp}%5oRqz>rLIZ)~N054rHCz#rcwedlql>EoBah(%4gBJ{2ZD#*icH0{c&P{r z6m7K71!-1aune`OkGodoKU<2^f4VsDu$HL@2c5 zJ)EkBN#?A>%JWbGsQNoQ4}|fL&~vW(u*jzcWh`DuYvqI%mQ*N_Y6nV<%A~=r-x6S8 zpiA|SkRJv-t#&A$%94v*Ijz05u0rN2_JE`F>*8GHq7aVX%&tENvf6GuR zNZ$Ym9`dI6vMlg18mRzzeI5P4oAocxo8hc^?(dbj<^w!&NGydiaXQS~vdrml^NLi1 zyb~|!fz!E0h3np>gW#Q`|_#% zm(i=04jZ;(T7`pspqz#Fm0eFlo5+t8=r2gPZTx8b`Y~~Ug)PK3fshHT<5o|5lq_83 zA+vCUur1)E!FvEXcF{`89It3iyitu}3?NSv%>zmkS%cgI>IfWJ2^IY=bSl9DP#y+( zMX-@g^f^3(<0O&kY+ok73{1PuAHz+OBI`CGb>m=(sy5TA@S&G!9b)@RBxql$4Hli1 zi_2)a__r&p7xi?O`t#uve~igXLLnCO1C(^OK4*kj=ytPEu;}H=yQHK@X|RtPfYCXr zYM;`o;(x!iY74Hi6&F@klr-i&1b9F-^BAt{GEck!5ZD>BEJgHL%f_@hP~Y3mK24u9 z3Tcq(!3G$^Qx{A_FxNP^6?J|>M2N7JmDWv8`K{R23T(chr+f@gfVLK;gb zG!WjjT>H?ZX>_Ehm?QjAzzxNi)l0bwD~8q+C>41Dv^C7AhRqXw%dwKb<>2T|<-te1 z0$IYSHziXg<5<9C<6F*X$e9ug`?SWMkrr1o;!nv*l$o0e*JW%S=O!*HqjYsq!$w0I z$%*D0pSeXXH{YkUH8nv2MccaFQm~hBJLkG311&@@9FI)LB0~eo>Bz*;I;b@>HdIcBk`CA4fgQL;p&~)rD-SzimOsA;3>8xSzqnyq@ zr;snYwqDHabC#T(HCLG9@}<{G0}Nugl|)s=fX53o$J1&kg`3J$RmyFv89p!sQpc{U z8u$d&_9Ca(G&I1EE@AkqDxzXnIk#0+DG+%Z25hsOBs6c@ITVXeMG}Lf(di_HX^$ac zG|6QAQa@>#Gs1L)qVtEYDy zSM_*wd~*6|ax69;tDZ)|N*1WAuCuETO4%_vMbTkAI-ZQjZmfQk%BhWOuB+oT;6Cgm ztd>=gC0{314fgiKk+DP3qn^>`S69+?QcLeVX^f92rjn7F#3;0TgOhiQ8E(e6b=I=3 zoy+TH4$c!{4ryvm!8A3u5!?oO+X9kvlA_7E>0w<;M=IWm4N$3qrsEc?bv=CtWYye0 zk*48{1M3SdDxQc;ClX^+d4m1nhgB?D1J>wC!BsIV#ZI0gIXD^}JTw@cMjY}rY}UeH zUvy0PPDs=65u`+N1}75OV-nMmDcs*01!ux*XSbn?)JNlElOq!&Ffk3Bd6628`jx{W zgTbm$K?KE1KK%qSF{_gx?}aE3yB@h$#)eI358J!KZ!ovap0Ypv8yhBZzLff1!q z$XJEklD1?xS}0^2$4aJ+7p`l2d<(i2*2HeB5>|%*jrHg8=N*8tAPSqB4Whe3g_ZIMq z$(T;sTEJi#+SKS&`}k7)`mqrBXJvSJ55?@n7Z#V(SVg@OPY|G568G~;#l`P?$t|ZD zSw=8z4a1`FYBl&pxUFG1NR`wmtt*MAv|XCUG%!qK!pF9f!bAWDWS0WVGTOXWRb~aH z4P5)po6TfUYE#NC78ea;qGdpD6|oSqR^3%83PQGCrop4eyFmj0Z^~pf$SQj-nhO$| z-|AHeFuVx zz)O%^L|(t#fw{Z-`1@dMU@00vaw$3RT&-SS9}@W_0wpD|*}!zsn*C%{W>(y~68G*a zx`N@c%1!&}nzJ;Lda!MxU>{G6FZqy`t10=S6kljL0rsp^4a^n4bU*ZIa$DAJOKw5B z4OII2ckghuqh8*7-%byGr@Qt4v!L?_C}AoLx}g96hLSabiU6zD4zQf)P_A%X5l)cj zU2f3{(YiIPSt0@tJ_QjPX44~K3pm6i9KpR}wKokHn_I(LN*CKEX6Go~(|5p|hs($1 zjY^CKKa^5%c^<|l%vx3j7Re_gAY5^k{Bnc$e>I!*2gLdVVhN_6Ge1K6gD@@@<(dH6 z%3#F~zy7e~5`U04xG=$Yq5o&)4X#36{}rb$NR&b}VN2D7#XQIUsZ@69#Z|oG=5s(-R*(#c`gky@s`a|Tu78gR;9UYsY-MCvI;J3 z+^uTEcMLHf_SvhI6`;-3Q;U(-(C7a>PhE7PutguYpo7=VVP+ z-1#RvxV*L!rzAjMDf6>^s@y|YCaEZGa}o$^t$q@ryDk^1tC}O4rA%VzrnYL*xkO#@ z@GpdopEac`b0q{2u57Yz90Q~~$i&*tm~VMpwAP4_(QQ25TL(n&I=eQjXI>lWT|L6w zmYT7jf|tin*o9i~8Q|psX2NCh6VDGOFBlmZ{f#;NTGg80UDcZRTo$@&505cy4z-WX zmmD*Vkqr&J9*bVPZrErLJL4Dy!$k|&0n<$|M>8-hgge-u>7ZS7)XIE7=;LKj2Zp^( zFJ(;sby_qh!<*%i0m`TV2YtQZ77Krbw^;xnFxLzG-~zxhI1%7=L0d~ZQo+|Xx+XKJ zkm&0g*VO(IdynP>>i`ZL2{${tL|CNqhziGYs2XlB&H;x8+{4DH5ja$WzSm|_{9Jy^ zxREh+dT}L!nm?#fZ6XL0OLSFiA@4%}V@uXj9YR4EP`9U0tSpgHr$^SA|Xp;LtMtTPy5K-=wZ7t?>UN?1}7JM;V%c?<-9+hcIot$Z3sb;2d zE^8g%xdRs{?P9=&%oj02k_WV_H{LTkxe-ZNYC>^)gjm(w;H$Rv7-s?KZ+T*nQ~17^3&u z?el~eoG)05Ik;tlZM?XB!iH6_T(G3XtDK5C-GwWT<)#Z8Y|%Cs^z>3FZ55ofX_Xu* z+hK0Yp3@8LrW26%XiyQHkc#_S$uTfNKu{ulUQyLUiv_&m*tx=tRY1v}uI`R7{#jl& z%UdiGk)SyVdSz~FLT#&d4<#}&VI0bu@B5!JVSpTzq`$DnkYN@~w1!>>k*=2T$g!IT zM(eWtroZmGbn}|)8d$eu9=5a&y2Jo8%CoPb2wkuhHwV)#ey^)d*4fY{$Daeo- z&`4eYyq5(Wf=`J?deH=-2kvLTf+e`zlR(@=cf==1Ft2?LWgE0?E;v@s2!a2O;W%1L zxWA*LvjzIIi(jpPeV~73pQ-|~%c=sh6Dp7~uknfk1RwFRGGP+VM$Ne_SbYN&VVqQU zJ3A|tv0l{O+BH)-c4=@Vuis%6w0O6GA(*y`FqAh7xZj7fled}uG+a8PqL^z zols_PV$%fFw~cdwbg%&q&*a@v=UyP=wWmAxlD1Er4x&M@258jw1;fQ~#-Y6B94oC? z_z;x~s`YX~+uLbNT-U;Z7i=xy4**J;>u5Qm6E{MRQR2I}% zK4`Y% z8tHtQ1=OmZB@j}b4FF1c)OTrB6A#EI*U%SF2mOS?SfF2_Z@q5AtViJtuvY|~ymX>( zA{m_+o}3{3 zImVoCA&<&5dW2bjAzm2w3bSozQ|yILfzFaUgg{1Ris^HhXjJF}E~mZFSD=4^N}yp? zVeH`VDNU#)_}Ym$@fVe)7bQ05hLEI7OVQ=Vf^vUTUL>9J$M za8uTL1>kNc;5rI}vC3mdajgkQs*SSU{$odx_SR?S@KKb{<3?zS>qo|?+{I&=uH)&B ziOlW!p`$~`#*Yphnz>yc?vA2F9egY)%Hn&C(y#JkNs)SuoZdwTZtp(Q<2X)nG2>3m z40kV?cf=3hZceAB=8laI_g|0n9ppRTguX**2&2Z&W9t)k35A}s1}CTE$;s*1NNj># zsu~%?IDhN}514cy1#iFwHQ)?OxQ8WF#zqY&!%{)KVkoYv+3<&qS-vK&0b!}Qe?4_f z-#RpqJQ9f|l0(sf8T3kL$$03$9h6kB#i)l_%fYy}O;Lz?C}IZqN~Sj-(Ii|_hV{>q zfu#;~wYIAVkcXAUg8;BZoT3^%^=_es(i<<7B6(;dta&F(6dy~1lRvN+N>YCFEG9ie zCOs5A>PsmG3Y)o=CRJ~kq8bIxswnfz`VIrn;|8(ByrGg+Vdc)mqse$&C9q|avOou{ zR1PbGTiQM{9hn-veoW<*SXw@>8~S?p(;KnQ8l9YpM-N4#Q*gakY$6ezJ{(b7!mr;t z7j>wV9{2~ISl~2{M~7k&RMRP=%?C&Jcl&rWF&!K9FmbGDe9kFlo=JTgnafBd5gCZY z)rsUw*1G_AsJVEM3ReELjPPV*_Nb|26KqS5ABs)E2qzCmr(?qyHi(tL!@yJpIi3y# ztOGta^}XHnzAjJOed~cImTljzw%toQJRC<228UvIkOd4OryK7O`hv!=u0zNHShcbN z7t;n*F>I>>{Gcn-=t|=YvQp3(UozR!M%q&EAQ`Mf2f6U37tJ>1xZXC3mcz(A1Zu=m z!E~26-P=aa&>dWMDB>#%cUJl>t}UphRp*xNq| z)$I}`BqLL?WMcAA6mRfmU4vV!p=&$nsc**0>t=yRmDw)yB60?`7xO_y+hk%NVDf`Z znRcg4yWFDUmmTal5*-+woIDf+I8w0Nbb5AAK$(?}5-68}wg@m$m6C0j%m}81j*GNA z+YL9(NssEigsjO7raX~wDIo27nNVEWT1zmPFZAU*yqr5YbWnr)woWNp3m4H%%j?4p4Qi(s}CKsTw@ewH}GnAO+AJMp~??=$^x!R?{IlldWY<0#d@uZU@Qn3eoHlezaF*x zvNA>v^$dj!bgBfWuN4dzZs8H}eJR0LRy*Ke-R{-QttFgn<0gDu~KO=&M?+N! z9$yYBYC|v|E3Kpa&j*Hs%{lFW7%MujwkjSkn=JZT?Y2MbN*!KZSJh6gMPww}{=km; zL_wI+(~>a7kV@GP$~;|hQWgu^4k1(dDMh@H5+KyRlJqD`=Q1dj0wJ$oS`0`FLSSoH z!;~CvWJ$_odQ$i$J$03rvm+EL{ah|>3<^DL=RiA~zK*^w-&ME)doz{H!sWsm?_!8K zXoOb+j}U|~qpb)?%3dj@GU+NPF?*$){75z%WN+c9N(Y2d)p&_{Rmo>Sts zQF@>?B)6>b5zuirjrZ}agPG#i)9^gws*J`0w%97+wK)FspT3E<1iCHhO5LZ=}~TyL!fYrjBN>zkPof+KUGt{m5ntJ*=l&<;OoV$EwtUK?gTf zu;vD%QZ;n$MD&Kl;MnBMP!g|B5lErPuDrQ2*O~rYK9w2Qd^X*rr_+Yx#HR4hy7OeV z#Pm!&5gkenO^!!m)QEwp$hdi`SHmg?$ETs@nmljvV1=yE7xoMp>bB1y`W@|;m5oJq}rXz79 zHyeV(MI+Joq(@pR6%T91Dqb7NvA#8vh`I1t+YFE{v$vQ#0Cl* zT+Vt4wb>suL4kfSo@k(SlmocUAWhK9IuE&PdACSEyX{ZMG<+V0Tc+{tfWYR<-Ljlc z&=<8bSyz_*gaTBN0oIC6g;-m;`hZ;&y1LR1ECxW$&onM@@<890uM;ss49ID^AmOAh z+_!wx8fpv%*LU&FQwjvzec%lYgD`0oZ2-`#C=}fF`$TZy?j-klN8Q?r7gm~Gmbeb$ zh3Ya;LwuZ1$+6L~7p792<0+gE_d|O1a))X)!ETcmE8GKixSf6|ru`e~ld3p~E34ul zhE$tV=oJLd7l!f^RtPS1kSu_k)m_ak*#)p3T@o2Iv*22q9y&Yc% zZ0u|tsHuFw5)Bxwip#XW!>2T?&*$L~6?}<}1*71GGPb#36u_E0 z$6{y5BURegWfmLuCBS8caD1&&aK71!C<*8xr>%GS8*73Z04znh%ThR*4YgAh&a8EdhSv-FI#Uu)ox zP9a?6^UkLpT>q!NcL9|t)f>FJ)=?rZ}KV0LD9cX0E% zdE5(tTh&!LJ#|xERa;d(vvW95uqi7fo3uztCM}8#z$V29L{Ky#&;Uu(AkByQ5FrL1 z0g@q$maPcdv?JsQ(UODot>gRiQCW|k?cJMOkT&}+rh7C0%>47uKmYvm&p-dfcgf;j zZj~zw7s(046(^!qPeKG2#|HlV&Ye3?8pgn#J9q9pZWx2cLx%CNAwGkKVgBQc5J8B$ zu9i67c0FOO=9~Vd%hOjz)DAlH9+y1x3 zwjJLk;swV&g}uWIsgCl-4oeaid1+&nt&Znu8~C(qJ;|GDPx9s)y1a=j#|^s58*cfR z!1v-JX|9&4FZvygHj5Y$dG5?|rbdv+dEp#6qmkfZIH1@eow>M$GJpC5;_Mo3OLs zmzf3fvk~_@=Eo z3lluPq;3@{IbGsn0f8iS=1Qf)5sTvJyig(%N+|-VP;#Su@_xoC%WuyN9IC-Tw4%gm zJ|MHmpdkZN@Vk1?%q%XhywaH2*qE8Uxir7L(U@C#Wf^aaQ)rA6965ERm@ogpwSQ(+ z=_Ue7-cUX|zqtmGGq^z6nB81kn_r&g_s4j3D?%!b#J4;*VfAXY`uq-yeCCaYQSb({ zlZN9)&yzaiG{F<2oIt0g1E;$4#w(OpSJfq~vxt7Zxv{deaAR#|gWuxhpz==N5k?om zPS4F>pV?g8Xe`d~H?jqo^z}J2--&{dRj;wgbE(9`vIHE8Utd|)E0>oh`&X?fsmxs? zDl9CoZ_F&u&ZjrcvP9(raT<=qH`Zoep4ph;H;p+|Du|EL&?!OuIFUylu2nl>cH`ME z67UMLD)UUXOxS69uFbuOm8N)_r#5IWm(edD%a+F3p3_w2jyTP%6-*opl{m!o8Mu93 z5d81gl*?uk1-@&?RZyYgG{-c(Qc$KRu|L+6*msUQ82q4=4O>G~$aa|%Qq({>}f z2P3nIwB*}1HTnUrqVYqHGrggXP#EC^E>LF_SzeOCnYsi*{MmutK*Xg(9aIbuL}ra_$GG$oS2H z)EXnM9%G$3YCKJAh%q>I1buP1C0!2|-Ha1==ZFrU9PUJ3CA5-ltN>LKZKa>}rZfy`je*RG6$j!xKVisTJTnQm!VJZ3i7c z83it*$!^v5EVm7S7EAb{rA*m@V*$=LtvF$(o0!|e6XfLT;{2d`9gK+Q!e|t>gCr1##vzO1z_&d9`iXew#bqL(UlK8^9h=EEqj8PfR+N|< zFUKP$&w?`D3~meXcF=^Ew!=gez<2vt3DhqfDj`u$YkuX+VOv(mljlY3cETdx^6F_^ zSRNnWv;6LYnR9qvD0}Qc+j7d=kUfVwcepr};<+1Zb`i`Ioo&P=P?2ERj_3SO! z;zMXT35yC(ZSLW&Toa~t! z*Lk4Jg^kxrj@bHJk+o&{R`G!CiDE%{#3l>L1GW=sFY}k-j`>?oQ$}pl;L;0JvQmPS zXq>SkW_cui!aX`DEWgA?h4keE#yDl2d6+gzIKLCURC@1ekw6}RxKO6bJgUmbI}W$f zTT1;-Q~3<0?+X09u*rYrRBmyBivpr{_Yd&Z2j5tINO$h{S%P4z2-$tK-1p$=bi*p} zmET}jISSXy7OxMaMfu=V{Vi~!Q*U~V;T^mRo*|)nL=Kp@U_yFCt0#z)R>XwY$(GZb zy=by0wftKyYWAX3MaxDA7c{6iR=nK|tjLK+_uHO~OHhauUJ+tms`gSLHL+4QT&Hfz zNZ_Wq6?hJd>gI3?gogm@bPGu+vZfh?i5vKFT_tD*Nd=XoM7Nw`H^BC;nxb133)Aq) zlcuS4C$acjF$ed@3f-4kgj!R~VdEENQ>C=xw@qsIFz0<`9ekLv`~L3K*ZXDE|yKJFb^3_(OGbY$O9|nnNiE zG15bIb4ZN!P`(1w9O}3ZASxB}244)!N+nAg)BH@n+z|7Lgj}mCLUV)(f=}b9`)U#2lZR8ZpN%7LXi*!UpJ>l$7QN%o&eGNnC`MeO5Cs+ndj5 zH2jqMt@Ut-Ic`$gyP+)?EbdzlBK{;wukCwE$t*I9d2&~ftR>pE{h1Qjp2~z z`a58XPkc(NAhdkuQK~{N&lCp_yCT4W6TC<_No6SyB+uu_m!gW#(3ZO>EZz=0C(dGmPYxR@XLsTxXqO;Ext8a)FqeklF<&48 zuYh^p3K#ZWYB5tHQ#IO1$xjJpra9#LamZ{;dOf^N`Y9yHksqBtS@|MA zijr27Vm}ne9-pB&VPT%{(ofkCQ877&L#>E0zm%c`w`+MFjAyNcSfvAr&)r*%m~;0w zr@J&-f=Vh9o7ycRAFAzA7Kwb#pGbB`-68;&&WVp%P);5@SC~g;sJ+u`B34=5*4%QGEjMjoZ zR81V8?}wBi02nINZJHS0j!o6;@=$(;;!e9b`!sPXKSS|$07{lkyBvuy6}E%Do6K^k zUF|&?{>i})gdR-%MBY&oQM?q6(?3ZY`A{RBE%y=Xf^YbLl?0BX%H@-?80bU3#19nl;Ii^ z8pVM!K>@GRCgm4Ry_@~fFdEF&^g-^Gx9xADD{~EmWSHu!yR`SvL%88S|B2@{E#7B{e`0B5S z)pZi%qllFi(tmmQtAr6sW#LdO3OeC6tZnzYD!@T5N>H+!IMi1EI6;J*av@u~eDjYI z(-O^+ewn4xzr44e+jgAJRs&28P0j!K+WIfvHL|6x-XZZKW#Qq`pm0titANC}C|p)C}5Z$Eio74qc3J zVNlex8|p>_OFGwDT%T)EZs0dKhNA=$o1gSwxjDZ!FG}z{^Q!bN8a8K^=k(eZ7haq< zhe-q4z0!Do_>=z1+T8q_dF?d~Do0$}t=eA4VKW|7uu}DX$g`S^6toSpn4}~Xd?xji zRQoEzq`ME@5F#qLB{W2-0scj!QN*@jo+!1>MXbfJPb=!1igS7QG|tV=x^y$CX-q?~ zRp!|aSAx-$AM8~wZD)u)lmsFtZ75$|=-NAc6PM34sUIdwB*UzhZj-=b%NY#l^q3#3n{1hQJKh_$SQ)y>3ejo6+Q$0KoMH`1Mg)jt^LO&8a-14keJVNidjwC@mfK%H{z9Pml3 zmU#`2p=}WO^5){ADO_)L^R)>Vo;Yr}jyZdCX6=QsOBajq!{)Fq=i8Qz?G(Q8_IU|> zt*-tnlyu_cK1zaX%)58SiV3rxI&Q^;OHZ(Tw{5yUOUk-CO8;fL%FPt_Qi8ScCSka2#E`&&OSg($6r$nc zhr|!@b%1E$T%gMoztb*qh2B+%@qi^*v`Czc*DmV$8B+M2b~mgLD}HSQqrD>0@H_1h zz5a{l%QK6c^XsA?I8z*U!{Lh~<_lx^X}9@5#_^Aq_{YSEIoxXTj7ciMeB0vxo*FTS z<78Oj`@*FWb2zbi=Jbd;%tXN}R3lFxyF6kJcO3B#K(#x!35jv!M3f^@9H)|TP)Wi` zf|&r)h_UUVUGs$rlyO9D69nyqQN?a2yn#vTS-5*i!*UXRLRuvXItinCCVAg>FIBc8 ztHqPhn<(BD6``S4#G$7+>2@zw>}WsKDKI75t5}_6o9e-d?J)NPhd3KSq@ z6#b{D8>rn6{M&l%msGn!n8Z}uG$qABMU3P$I=AckOk~qAxUGn{HjS!-INZ|6aRoKR zVdN&P5`{L^dIhyuw=3gQ{GXgUqKPY1r{aRK8W<+@eOIe=tOlTkRa_>bD#mbnJ?w_J zE3Pkb9UDW*-AEueHU>(0<6`K>#;MiVMNcF{j7^|OY)hC4Ai8A_%W1K)Y~udF;==5P zNz=ugTY=QNxv+dAH;-?u%`9)2+-N=`=Ff<^xjHwqF+XC?%`eVx%%eVCV=*ziNH39< z^;!!T4O;Q84)y%13HQoYfsuHlCe&O9?mv+26b_KtNf42wHk~H9vc?w0Hxg$araIy` zcip&SdG4E}hf4Q*QL{YAPT!`cBc0G{G3{{&jzx(tzGy7ns$d@?{)M z%>A~{U3u}e0hl81eM7aD-jyqQFKU4vi2VdcC6I+U57O;6b%v88CcZf$(86@Sz(wsV z^@&>T;EQ9T4)QGI7riu>Mbs>|n)kqenJsn~(u*BP8E6?_Wi}=US6Kut5-{6()+@0K zHL>}w;}2aW5gfr`hvOs&8?DH)StDeT8{lFKzYz&%G(ovCMyY7Qujj5^6u`P z1F|J|UCnHoc||3?7rvA{zwGipcQj4eL6*3sh5eOY@2*dmSybeqRFJ{xy7Uc@mpIHJ zid?vop5?Vl8SudqhwDon1$!PnRs4X%lJyz)5p3*_p65=#_%69}f@^*SZ`=2l`t?({ zBMPH3ApgXyb%*CVv}O;;6{<_C#)6Wg#hf+_~oKqD{_NQY_7h%hNz|SsHs|y zJ0VG5vl%4Y=0*@j%umdX2)oRP-)-6CVbB&hit(tqfZe!gB{pMbwLKQc-ac<}J@Bn4 z8Zp-_hrSnG{*C)IYm5@jU~7xv^o4Gfdn{q1<9M*r47NDdf+jJq)(>z42k1*o%$Oye zkODNi5p&EJ_L%7exHDyW-o?>(KUkaOsp8EVF}B@r$q0awkZm$ch+ZiI4`OgG3=50s zl}lGH)#=YcS6Ads!0v(B9+S7&Bx*7qdNHVpY4s`2a%0nyWB6BmeRzD0^+JiW|K*+B zl`P)6iL7SReNeY<`iymPTk=^_=6U1oTUG8M?KFgeANNh4U7NXfZDC{SrN;a+jJI=* z)y2&l3(M<`>kEq%_+&s9Pj9st2JUAcH%xJzr6*l_n-94wKf8kX(KQR`}h|Ad0%iydVC zNSbyl(f+l^nhm6UYP9>txP|b%b^4obj8{VDi(RGJ?s$n?p`ErJ;QD49TP?be83j8` z?2>1eURtFkYU!no4Y?}H-LS;2t2~zgCGuQm-NPnC7Ez?^vTKlV`3b|}%ar!v1E&$) z`^L8V;ELsvbQf;yvMNnox;$Q|KbUy3YZY^Nj1u`@wO~>7;j!uI2?R5rsDl@@BGX8t zKgiH;&ZC+ss%(n#DtjWg>rHue6EhdiSgn4ND01~Xr7@nm-+ujY7%wxE-*dRJJR(xT zAXFdlZs6UzqyEd!afyp>B~H^j>b*xN=9B^LPw<~T$5-TN!gWj%iD=CrQ*VY6?+L11ow&xCGATj~@`cZvSi}!SG z?$1F7c!;zWxx3hmZ$*KhRPb^E-Vs@2j^ifgUgRbT^ASsJtrMr}1`R{k38RIe<&c#i zYKfou2}CvJCeT52>N16JV8OW{cajHn0aM3N3+l+d5RlId>hq5t z@}db(O8c9zX!1FsZrSHv03p*aKY=1BUZmKzJH-Mbz!H~dHwpex&7tKv#-6m z@Or#|rP=PRxHlJGTw_<za`A3TS1uJ3RmPPO`;tAm+xLl04l0R4@u~)BF-L@5uvfJdafZa9-_)NAQ8T+)H{Ll|U#iLiQOdL?S zdq{G}jrIApm***7a&}B46CRzsGzDCq%yxvzmLrlHGLIUU^iVrb zm4w>K2EZSXr=Ey3q?Cs)PlzAg+uM_HeZLL?NcGD|tSa^o;Ie_0f3@rLVn+=;bzeBA z(_Z}Z+-77&`|5nQZh4{WQ(zr^*1c9%&4gxplGCoLeqjQN^`^2Fwkv7H*^w#5P1>Yw9SyfbnWZ!a)ARzq6EdqAB*>#W+Hc_D z-PpX)iCp?qHLFx5D*NaKD{95EN_^yvr3FYcJT^qCevoi)3QALpNfv zIZ<=+xbg5s4KHZnz*f(d1M->fN^>V>CQ%#JAo!(eN6cY<;#yvuD$%c~mv0u9W>!TB zU3W$-lL%YnghgB0tF~%HyXwjcqQo;z<=u;qiz>ubRI*L0XSvDE|T{xOgHse z3LYuMh3vUc#aPwSZPh@%3UQhre4-6IEM&eDH_~WL=&}M8v8u|>87k&*c9|2J)>YEP zH1ZXou%M@8bX1J=vKp~$UWJBrP=#H`rOhq`p#9M4s`|6m6@yM zD$rfa5-qM=ndl0rDJi0jyk>K7QEFiF(iDd(+4J?f5c3M|d4IRJx0em(j(Sw1e2rGd zfxG&dYAdK(RI;w61VLUAqmGO}$8X+IfxAr(%p(FUQc6y5jx*Ozc%=mwj)~eB>~5*y z`kj-l9t8)P=pL6QIz?JYPi%{yJy4=U-8Ke|x6hB=vqZ;!Al(hl9j@deMXtr~p`Ays?>Dt^w6cxu=3 zcGy0-U1y?tp4Qt}JAtzTp$hi^z!NoUlfmEq#wm&!?F~^Ou zi!SV3wDRd_fVEnheN+ryPdkDS^|T}Sry0X2vm$#td$eHhS0YA{(OkbZVs2aZ4z81% zZI)OZ-X!73q%VWOzN^-xSr~I2&6yX8R!Zcy+m`Rt&Eb0)7cTUQ0`Jp%bM1!h>zEIBvf8*!I8%@H)yvYA<_oGVhQrjxlFB~neh87zD9GfF2vJ@YrD zUcW%~R}R-JE^Y@qEJPV`yh$Hr>48hU$d^~M5!Pgd1X0<)QiNf(_X2A*S3OGCeK zGF9ur!>V49gXhx}cy5h4n*yiHhkQik`wnR@{lWvos#WF(Q>?2roye{ljAi%ld;ns6m_#2` z_t-qnMFO)VxiX~eX7mt$!;+IO6TL=>#N@0mAMbC5fBf>B!AlFb zP|u?rpS6{hjZ9?^38Y2@?($hny)P$uS$PsA`+@BPx_z7?$WSBv`Mqm1voCJ0Huw!% zzFO0OB=X6gw8X=_1jy7_-CVno0hf;_q~L>iw{LF#+U5(zzGzx85xrMjWS0d^W-@=ZUzL-K*M=ML6G6+&W1 zDch0s=XTHafnGXr&FCrq5}VT3KA2*;rVi z(>z)3gL3TK`|&N>p`Ibo<>mR=Zm_Z}&^a}CEju>^hv4x~;4@I|#8I`$pFaf_bDK-6 zYR{X8R&TIAEFsrlTv%~bB(3> zjhic6IEmg*iQeNC@Q>wAc+XOC#GGx+%*~OiD~pZF@n46;s4Q%tISoGF3pu9!u)=Kz zWB?eX>g9Q{tXa;|V=#siVF(O=_+hRDl(R<-$r%DH8)7vqW3_QQ^5sqE2U$|Fj27pp z^0oQZ#n(1g3gj3oBS*GKo+45zt2yx)wXm_c-gtR_ZQ=TBjn(;{I$XvyQX(In;`@eE zOEa%F*5=nY7dPnbW=TW&l<{$#4U%|xa&>Lt<(Z9nIzd~1ZGB^YsWG>({-VxpbADv=VqnkP#|)vYaP<|!MD0Gfe$aLAA@cDmw;i-|I}S-n zah3&-L3$aPPGN`ZGM@|~r52#9sy19VB|7{lSma9qfNtJRbCX)UD4Nl_Q2uTjTdq8& zVh$~Ye8W+GwtI4G(~Zq|y(QKlF&Wa6Lz*lA7qsX~U7c2?)Gg5ohqF-!1xTs{7V@Rm zSC%oqjAxuv)lZHZ3cWawN1TW6L)lX!kg9U1iB!Byp48ul>*nUhtls$MS`T|zRadH? zp&g-)Wpbq+rsZquS{795VPJn~Xc8|??aDC}-k;XgEHol@FuiKh!=!eVf4`b*QYfla zEWPY~%^;yPp;9PPnfgdi8m^mAp0plv#i*DrSF~c!mGU!OH(Syhc9<59!8U=8fN)0*hSeSNEL5Az(!lXE;T-g9Jx?aLZ zD;2}K94v}q%FVCYyowU*er+scTq=>*(r5&WJVN1!)>C_Y&OG#lw8;xVv68|lRJ_}N z{=EmS*%^)Po!m;2)_^m+EZMGDVOWU+@0)R5F&DgKkf;h=l=fG0`{K#>^Sg-nPH$hR z_j2Law@b8}VwvY6rw@vBymH5$&GC5;#D?C(|$>3}iMsCdL{M_C) z5wRN)wUufXc-?RGA#>CUEqj}d22sHjj6O?2`K}{>pqAR#Dj6Vn61x(MiP-8lMwBxKN)zry$HfvD*KyOsV>zSjWG0sD1qgYAyM*7=E5Dq0g)6^2x%aC|W$A$o zRnUEoU%?!|a^M`l@B6;z(wUFhHJWsLp?UEzhf-tJ-#C0Bk?g~u@&JxS^h>{e1}tUj zxc5}mXSX{snO_cCV*j4-6#A~r1xK~S;_6OeiPgP#0^hNW{gs^XPwUfXp-mD@*7fmdnSs|qOy*rA&I7$~GgUCsJsAJb}c}!YUf-MB; zOtwilSe_??Y4OM0>8Ll^b|a?}T2ZoZHeKJsGxj4Ci!1P%pTr{+W!h>X6-UD}3*?3k zzin<^7?xDz=%wL7^Y<0^_Vz|4EQ~aWA?0-JB;UbG#KIs(V43}#9f$hg)y_bu%+0nzfP9q)n=nu*x*lfaMLNd_K+a$2vTCjmIqlK}j#j3$%@ zj*@OJYaJgtjvF{Go&RqU)PHUP`pfA}OBq?sQc` zG(WVKmAG-p+zerIa!9W;zkM0L$8q8ErYN0C2dKMn%7;wNVcctJ{^ zyOAZk!C5`*AuO=tokRBJ+xP8+91;PRI8I!Tt};}@B6kANIZZI#L+S3g#9&>TQBgP*>%_z_$W83oI*% z9r74!IA<$^J$KA7&Ob!3w>qxPfpIPg;Pj) z-*8u*uO!+N&Z=C$gNUuPrUTpU2oEz+Y#E$tv?8lbZhvVWJeh2TRDiJBkB4Z(Q9ZQ4_7Xpsm=1QaXL=)HlJj?GYS5?g=*X~rFY{1`jqrit! zEK>NTy3K{TtGc%y;z{4gq)Fjfx;vD8yNfMoVtTSpf0QkVS|1-rBntXlP3*9a>QeUR z;+dAY}ZTxbb{t{#vV{`C(RxqW_mw#(*iVd!s`KjoC2wbHxC)5OW??(|& z-uo%B1b_0~+}8;VOs;v$y>R|W5t_5j_har{(4)LaRUDuI0LaV{3| zt>i8Cx=(YtIXHF1Fb1cT#60TwaWU%zBrmdf2%u|J_HB}6v<=9qiJV4>+i3$qam5Cs zax%^7Np8;eq$K`7x{~O#WG{#inEhS^<_3)_FgE9w*UfcO2FZlxo0&t4PO=?DZek_w zE;Fsz++&`H?}*u*C`Ka6i%Uhxwv~`ub(0~29=Eo|%-f>9CY-Y^9UQi}5YfKuee(lm zj2hi!U%67JwCgH4QxMuJJAPcvDWNHZ5SLO6raRmeL>oOW77Etzsfp=Yo&IDc;M7EY zYJv+YUyrKE(;*X8`hCkQ#2G~`DqNUch{T1h_eg~_?U15MmjkNr`-{v6xe4^-Aj^!HwYi?u!Qa)z8b1Y)+g>d)=PX4Dd-p?g>YXfD>-9`I z3lB{l)GKe|26f(1O9#kFwY!a97qNDwc4e$if0S4&*&0h`te3E?rbgxTDHqdu{VY(sS~#+Z&!K8>r)``3I30s=JtF~bNk2jxqW{s z%ZwSj^dQ%swZrhl2cG4`UJwsl$he>sJaB!Nc?o;bO-9Tc0h!}h1KiZQX2t4KFYn=@ z&t1(Hq|tUWT=%WKc}x(TpX5ueUCwO)3)kkAnqwGr6&<^y{BEvsxAUF)Al{MK+n)-qJo1f=4f@$ola?|8P?G6 ze$2*!M$zlhkR`cYL#B@06iqh{Ws3GG$p2}UNd2Dk{+_vLU3DtFwhd6?ru);%Z$uJ}5 zLT$ z@zzz10X5xOfol9CK~q*cpn%|*tBS8Utkf@h8)9DOo(&b8&+3BzQt_k*6@E&p{&^B- z75__W2t{PO-bNb2D$ko=`%5ga^bNw1?0qaAa#S*+n(PCZ1GuM=InEjoW0D$A`}tte z>3V8C-Tel)p5i-WGmuAA9RYxE1@I6bql!F_#$`erQSAv}d@JD70+@Wjxhdkty-6cJ zsWoXdAgR!k7`oY$82Vq!#LzvcD%?y_6^2!@q_N~ z6lmRoOXO!&POp)K>Z;P@1b>FqTq+bzqEnM&lXd=ASr6#62WbPgaHLGKXy7oHpHssVahu^GB96PTcA7J*3nR+LA>KYA!v-wIR^lRl8JRwUtu5Df zEl;b0&pdUEt@XXD6w$00j^(?RmKE8qr4uzLSF}pIiWUtfJ0xA?%0#Vp>2B9|Fxm3~ zT?QoSp^$%2svCFjQdR-^>^FP7Xy2vL>{kw147hmj{sHZ~bTy_g8{z8FD#ygNU}W#+ z%X~zg@BYpOuA$&t=@dBMg-;Najw44n0KNf0elaKF{n!gyT;2HgoVqbx;klzc-1m&* zM57%iyjq_cn>1x!CuVE(4#~nQWhPOFc6_6$MlCziW=Z7QvHCZ4OjB3RNI=TyNdSGk zCjs;)x&TT|0!joSxHg=YCbNl-z+QUtG-i>TS$H(w@BajhlZ ztx;2&@kY!r*kjRF$1~%=qp(&Vq4qzfXw^XQ3keC~DZxX>wX z*oqsa9FFSW`mlBpVOJ){r|a}5rx-zD8k-a@FyKsHLD`uLNjQl^I!DsoRnGXMPJv|^ zjkZ}4*L?T+0YWUx?tgT+CR^UgZ;BYpM16fik-H-3eb-wV|GRJ<#CJxLaVhnBPD+u_ z$yg84MzpU9oQEYV$h@9p&Wk$D%m>MX3|pmPcV%H`eE_L8S?Nro@oLLN5>( zEmD7wR1}CV9*$g*l?l=EjzmJ1_FbgHG^7IkQBvXV6JOMvyAg5UbAR>_#s!nRz*=8C z++ftZZp@`}(qd0S>0j!O#dH(&UQ9RZ z%#&wKBRryk8Tj75x%~2)yxTP^oP*7mU3kTqaj=CQ8yhuWadD4~SxE;^gv1?t8{Tq3 z^9^Pvro$5c0_}*|4k(PMmV&1`=)!8tcU6c{xFV03Zeq6FT^8eF8f_3s@q(p$hq2JK ze3R|dk@$YliOlVw%|`f6kinhV^7qXk*=7;$q}z-t*|Yov<%O20eD1_pbln+>e0aKg z?$-XO73Pn%1jM@J)H{E;dr~C->(cuv_(!J19&1)9a9ND^>RK#a zFR|9<%Z^B)3B7S1n+(iKNxDSv3|jp}Vr3(itc3(o(cYr!&v)~=iEcVBmi zSFBcD{zxw;YqQdfnB`R5q=FC~5j>qd@m#XpY0KhWCAI`8ImVP(T{T}s=I_Qh5Uwz; zb&sOX#aL0s%VyONF*qE)aK1268=K770q^--QtYA2I9L<4oCnhvb5b<(e4FmQPwQh% zTB@`+%F-Y^#P2zopaxvsCw{)C0f*dDto!394>iv7o)tybgL(q>VM7L|J;mGIVUa^p zQx73KsPbem)-(l#2CNL(ndWqdMU*U%Fol(2lQK`F=7Z3t;4&U)ngTQst#@W_X<@mf z0Vwwvy zkA3`=jmG?|s|#xsc(`$MWpj<4(c6>>432d^*AtiOoWB8#3Ra2iVb6o*v7q|>Tp z^xtQNn4nWV_-Ov6i7|kBrkR4QCK-b#rxb zWoE9iL~(l4_9O+<6d+i5o>y_F_B^jjBgV))a|d+vGBT=fmNirnoi+4gsn5?510$hU z+cP}eMJJ?t1j-qpUnJmlR|R|bw@}Z>2k;t@oY__Ra|eWKy;-&@e?YmkT5)Xo?(M3g zQ?+fm`c5#VAl#!0>-&4t^<5%ZADhx1BhpFL)8f9|)8hWU$F$h3y1?(gxU;4iv!oNI zi~1|vQCTkEbkLtf!gYx#;wLVPX@e=+FkK%3#OP!&UG5>NcUbpGLE1rAk>a^yJ2et= zw^sgsp#nSj{X!A8@~Q@|Ew4ger@7fY$mec(aysOmfuy~e5~l}Mz$NrS)uaMdHIf&+ z8op&>_3F5aGFmZ*mH50W875HSKUFr#%&QdjU#nb~g;x(0omwGX_VrvSBL=UIiH{><=cOikpg`zi8TjZs6j#~h_eT$To6VX@ z@Sv{faNjtnaaynm@qp6_jtL&*%K?a2pag&nS8?JMh57M~g$@3wg@8$y_JTVvxBaL^ zUAy+o8imANHLbwmLX-4jsg;l%cF`D`Bl5+D}7K(>_{y0MF2y=O#QH z9aDuUm%rc#{Oa}DdDCI>P7;LrX^y$;T4W0q?;~T8Zbrdg%u@3w?|0X|v^JGI*YDis zPCQjU{VTk1euYm2()EIZ`^^b%49b@QK=3 zP2E`Fe8eG3?5N%BlZ6fPNQqeLO3Und^~>+h*h5wc_Fn2g+--FbIU(%^9)PRe0PP4M zhX#4OERL}eDS1HYh(qCNy28rU4wO0KH03__OdPaXrtWT!Asum=@`Z~mGPxI!G(?VY z6TrDwR@UZL*XGx;YOA+L#4Dll6_0G4*&@;=Ad1M1R<_9FnO5}f-a|{$q9BUs0z7ln zcEH0KCHt#?c){-Z$o%JfW>r>;?C0osb1hf(+|CV?Nxb;OFoP>XtkK1jO?+d ze01yhSgkfyfS0dXrSS4KS~I#nJ>8tTdD#ozoVv0(HP;!pCug_V>`MGnbI0RPVm-bz zv$ilZcP%?lL2~)t5kln`Q9e6&Esya@K4*ZkH2Z3M>em z%w?;+6McMd?2Xr7a#kj8E-l+Zvvq0ajqA}(ulDAv;(fA=s6yYgs&Ho!-Rp^3-82)e zJ}lCxPwPugJ<)*E)%~oIv8KLE!#;-p(mmdk3pGYpH%Nohzi<) z)A6)}(KEcDNX7uGvXAD=GA&dg=dlX&?TneYn<{d`X~NQryREAJ_tL91coRe5W_c`1 zVmop}&86v4&Po+M^F_Uy_vNdR5%TgiJt1n!d|~*onT_9 zL9xs+_S5-7aqLxX5JC;^!=lYN_9~QvS0@!2pDL?hhwZ23AJWPrBUAjDvf^>-^vH=IL!~~`adf`@U1|ELJAAWF`BxC zbA@M9jU_XWD^xk85N~ECr+$-1?)kK^=QblN+Sk;cN~h^w(M5Er--6~Tmu+8C7Y|RN z7SWYbce@u-JhGKQ$n!y{sETl3q9+agrJgkO-@V7j?Pi>|>(@D&=?Tev`h?1?XT`C( zf(P%`gHB{KbD2lEGnZ6IWT~O^YPzcDJiFv#0S)d!YGZDxCucJG;3?N)O;ZO---W78 z34o$XoE;m&p{q@Wa`~chz#=12shFaGkbSADEZP+51$gG$1z6_OyG&AnKR~%I)k;9C zyXiC>k0OP-%%ZMT;!9WBgL~K*WHqDm0Zw7$_-0;DD?E89*s<%2hj-J1D9n5QWk?9iv!*nnQR!S<``vb4a#`Nt6Q?lL(&_HKipKz?EiELycuQ8g+mYNZAw@e<9CVVb9u(rZbe_CJG zv9Y4ZGOG8utdpL@D?Vcwh8xDr#wm{V7p*KR@vrq@%9S zzSL)&z)=^@y9NdgWANBXaRPP<$*1Kp*vUS_7(9(=!$*!9#=xpHil+?2xO3-@(G-PsGh&XrG4RJn0s8h} zA49LHx9KU^nIH?tkL%%Ph>oR~}QP87VxJTKTojODqNSC)r9bmruRjT`IC zca~TjTP?1_V~l1o0FoO;GApX_fhRP4tZtzaqahq`wRmQlOGdI0a|lnfZ0!A=XH`O(w9Nw zB}CCKl)*Lae3_?~#y@c9?ephqqfuux3<7V|PbdsiX$?mYs9~(98jc-M!+1|M96z9j ziF^$MhGBHVR%AJR-s5vt&>!DtjivFEhB4R&0YVc2Z+eOlGVuk&FurUU#*8R|R~9}b ze*gKMJ9j=Ne*Y}NERBENFg|Y>ze#_8l^FTA45RPY4WsWj3}f)iVB#-hcYYkM=KBy7 zC$B}W(_)pmm04I{4y=GeqC*S-4YkQX>RCRV4N8j|qHR?aSgWD~Jcy9xVP|?ttzv2B|_aA-rzd5!!^anq%|F{494^Dpcr~l(GKKsA@ z&Hwvj{%f=SfAsX9J@tD(@^_E^-sHdg8)ts{&A0x|zxwmgNEULV0?z&OZu{`tT8#Cq$5!}x2GniCILmr z>Du%q5bUlPfN19y{DgUVf}I4SO`5Jao=7Qld9?P~ata+SQ0T8I3f0OfG&xzj_GWdu{ zO`Q---e(*&VyBr|tOg3byUt6MGNhzyS@R>fGk~kWu^Br}THX(-s^b_Wp+np^6~>?d zML~>xyj10WQ0PYZ{y}4D{J3HK$Z_KdV`&`QZTPerh~^~po=3zfkYSwZ7is-j*zpr0 z{e*-a*c#($TVp3A>@iUvcI3bH@24GX7LQ|}VlIv2Z8B_hpEZoW=M1CoeYC%!z0JA7 z55pS4*EyIM9fqwjeXzR{8SOZ6WispxX>tXRvPG`LWH!hkvUfepk7YVk$R=KLlnEe1 zGuf_oViw6XU@8j3IBWY!|W<;u1bRv6|J7$0|E|w4{8r$ZRiY zxxQYh!xEn*m6#=X%P2;t@WGBue&fk1@Yp%SI07EVH~13Y;5mE)YiHXIxe;3wCK6F9 zkJooero$4Xr8juw&sgPy{j_{pOeIImv-TCVYMYWJFnE>f;3H6Ny1wK3il8t$>Dk=b zR~7~>^<0lxv10Rl%^Z7$&Xc*aJi8IIwEy`UIEt!#BWT??-sxRbw6OFx6|u}Vf<6ENgp>10~^V2 z=hnqOTWs|~vwvV1ecx*s#y>O+4m} z*kBsQz}z{*_zoe;K5Q5Rf1O0;+k+=&MCJ{{82H)KhOrxHcg!ukB z2)RI1_q6za7IvBEkYnP{dHfj?dG8nB7sU5%@%x=U_bR$Di-UpYOq+{{mKtq#bU>e*^#A#~+`{e4cpEF^q@5@P#jY5dZig!0uX3 z5dR>+egJ>|E2Pm2;Gc(Av^u=~50LpOWVT=x{v`g{#2-tgt>K@GaFlg#`J;Ha` zp?kCqQ(ofk)CsYhfcqH!d=!5^Lh215Hr$=7NV$SK`~&Nl2Ha)*xr9Gc_%n<@AH<)F z`18C*sV9-}6#hH`bO{Zzw*9li)I@?E-t^i{@VJ+QoUB=zprhs<2QDhwOVZw zzn9jpZ{USd{N7@dm#<7sO;j$AO*bo(_Bg9dPi$STOmDF%d;HSm*jAHOan-w4O{}QJ z64Gm{Lc6Uty};h7#!eG_d_1-iYmAtgei1W&_hB;geT&n9LuKZ_0OIsyWVOYc3I}lW z|MaI=8Q(RT`u?smHN~zcu77`5!J1Zd9}^>$t{Sb8K7C^oIk(CUvmo=QeNb~~~? zKdHKYc8g)Rqe2=Uy~X3UvRWwCGOZFJM`_}`MS3GQPVznSSS2PmE~RLJU@a>SqX6~E z`k}40A}hob-=t(xfB=~bMKGJ&3~r}YLQl?S+hM28+Ol{tf16oevfVx3MMO4*a{DA<3VUY03WM46mGJ|$Gt{O-^ zD>poPRvhgjS5^qlk`?M3RUj?X5deodh$ZeYHK=;Qy_TysjA)DcU)ggb*6LW1!VtQ% z+iHhl6x`mgwwTW%OHBzXr!uJqi6f|yX0^8zTf;cvhB#+by9!KQen##(xK@>@trE_N zc+L(}iC|5hh|XjCLK{TcGLDPf=$8B^Iva&@y#mVvc#^Nhr2JvIGvG zJm#p@KvIu6)jSqdoFy^y?Pxz#jECO0Ej!fqd%&S>*$MO1URO4T?zdUIO+H~V5moqB z61GD%+o%c}p+XhVmVA~}EyuydstO`E%bFk;WL~<(rTS4KQv89zL=tNzm5iMNBPTPq zTm;;gb))|>$4@67Fh#N(CYN$0GFffQZ>6FNL{_D=+A`^pwI>^w__|>ie38MMfXf8V z2R|*!!XE=HgAewRpC*5dw?A)S0|18uJB82{%{qYrz(Z$EBeQ!{Yqjsa>6p7@ia#=z=v!+60k2F;hH%LE=hm$?^ zl^oc%Mrp}jp0&@S%V88Gfnrpd#~+f+icdL0l$u0L%}7ugeT?_q#NMu0wpU?(61l19 zmwd8&+q3-YZo)#wfmx%e zYCH7eY83B=)zC_pSy+6cscIB-AR?=LidJJ?O~Fd5fdp~5Rkfnj6p2M8pP!NRV8a4{ zA19V?t5Ge3@tND&Zl?C3vW6ndZ>dUhn0A`2kW@WM$M<9r5uJsNvEyrN%KJ*e*ljp} z=RgsFLF<~R(Ze3A2%JMt0H@~K^0C;`#{w&x)*d<-g*(c~oui@~yD@2zI;CMb)~XON z35%d!NlN8N9lGtfozX{gwFrPMyOOj+wfdLV(u^au)aNL|Yq8U1r8GZI^D)P?zSu#i zbO5M#TGp23CswR-F;$|eYO5Vq-Uw2wGQ@*cC{@F9bkDElIXv_c%MFQ`Xq5zq@{-!Q z+9Nm2&^pH#l%1n=Ne#GyE*mJRAwRi97f4DpTj6f#DWN1rfwDY@_8CVsvk z=lGP|f8O&}3PhIUb`(j8+LTgteLHAt+8#A;IlE3ZjM$cYTQ*NrrgY)4Dl=dlh=O*Y zn#0l%`|j3Os%!y+m_>=LG&XXsYB%F;D@s>REHrVu2`yKl3T-)VtMe(e2LE%V|D)q^ zyj=++ch^c-W(B4C0(&QRw=z>Njti?4)aGO>UChv3{JWsNgLFw`ZEbnMo;VnglmIF! ziyOLBH!u$=&$TOjlad5cuKZ9b46XD@C1LFlVP92^I0Pux7+HH=OGq3tD8xy`thTBZ zQ?*!YM!#1SaP5k?wkat9=1HR3r7Pl42>-_CW$pWAV`=gFWYtPB$IMAHvb7P(RH2M)pbqbiS8PkC4nzy3w#6j@ zd@hQv;~Vim!E?vIVhkF`zG9qzvP$PBRoe>Vw&l|VLPTm=6GKgsc97nZo>jCHCz{a? zLleX0GR_=@ql0dcRNJ?bq}q&v9ZkYP9S=h0L!$6qg=`9xmpQsA5ql6-Tij{#S*Rbq zL)9#Ys7B0I&I&-QnM7N0CGIrEbr9J&1aB+dx?mWn#=vQIVj3d}N#+rBj%US8DOfV6 znaHyRSq2Lv$~2Q|$Ran~*3C8`vBFZP*2R*1{ccrq{3J#d*9L{>Ek!c?GRY$%oQc2q@R07~~+;^xdSs08{R>nN2O zizTJElyLxqq9TKd*yw0Yzli}Fl-!fJgAS%;nZFy?g#F+nf;14< zkoyRqB;1p~g@AX{ZlcOM>c9XDuN03P{C1DaO%RRWxJn2`D3^SbpQsDhQTpZ@L_%-4*`v;antq1 zH8uLT`e&L!N&KHp*XJ$HY}`Dc#q7AXgN~oXIPC|;VxZW_#4&!k3R? zzSa}GRxMUTu~w0pt5u{DZy<7qj_Uxg6#?0kHa%VZSOM3h9iqlF3j0RV4yiUTSKCR{ zmf<#BCOBWHQS`GqD$Lrb{+YD;d^WWe=Gr=iwjQC|*x`0KJ&wPluJ58nvule22n{}6 zY*6G<3J^k%N6v#9AY5td=Q8pqp?=rVA>&=q$L5coe^ z#9xD;KD?A``C+s?NTZD-BQ*DTp*iHB{ z@+ldOI+Z@cgFaK*?<{g;bW|$?By1=2<nEqaAUYwTWwtF_ z^&NE4vNAr7xxCC?12PZg+MU?7GX_X>E6uqT#1*>xC~=WyT3!&@PHcyjwxuAlRd+NW z$ZSr#YfjWP2mO08xMS?;KM4PtAz~c*?Q#gaZ1PAR+#Slvv^=+D{dTkbi=0{4}$TS1^rt> zWLx0ZRAn9*KgBVLI{uE#lDsN;$8+rzvuy9FRjN3J$c~%HtbmhBnCMo(Rbp3-s6-4o zxsy{Y@W2^aT3xc6BAF(M?2BYcnU@}oVoxP2OK!JQzSCO?)8kDE59jN4!|Esl4+KHn zj&pMwDq^QSCGp_@lvhQmGI%4C8vsl>5)O?E=i;`PvN4Z+ysSI{^$}N{B#L z#)eDVIHE*$Gsf(L_G+0OZ(%3r=-WuJPo`=-!6EyHvC3p>CohFO4I$|5=t8^WC2j>V zIK%BobCAU#z%H0QUc`dH$);6BB0oJkVY{KiP8dGrsR|uL=pG)xP`NhePN&gUydRHO zoMw8+PWFPmY#L?|rG;Uo83aj;KvET4&Xz-_uV z8-_7>^glF=!F~^ZvTs65;`%!&1yv{5^XYMq+pvIz*dJ-xJ`!ESNW&{zVHhiCRd}ve z@y0V!s}T!>(S57!VUt8uh4T+ZRFUMv#6zNX%>mqpByn@O`bMBkv={>|OI89Nl6UK6 z8pN6~x?pz2Ozweb#JDBV4;*%Z?$;Z%{NV#DFxD1)AkgG*)F*#~Ke1fm16eMA<6FYu z{7n9a^;P~J*5F|=lId0LH#XKXeOmjC+t)H3C*Sh-RqZ!6-7@`#_WP#xdqMmCqV{`H z`;G0Rtmpf+-=8xK<2ljyAJEcqyGFwQkoNnBwckIg{r-YRhab~^e^LAW0U zZbAzjzNDq&wz^FJDJ}gg+V8Jwzkf#i{WZg&<57HmUhCs8X!kA#e12Vn$95Gwfe+j%Brknkga79m{BH>-eSF|@A>n^Vga2I( z{`WNaZ)otiF)s1>0}cKUHTZv_!N1avw&?a0;sw0Tg9gBff?TJc(z9^SiN`wVlj+A$ z26NPmxn zC#-PSe((uO&$K>_Cd?zebyb9#xQHU(lWBs|t4RM|q+gUxP&yui8vI-_eH!Vw(wCx2 z@E=0@2-2rB^&lX|;8-#JD$@T+v7Q;Ee+lVVGxgj+`p*{AZzBB{i|GqU|Kno)FCraA zqQQks{fkJyRD@qf`ZUrPGw|P!berIx(;4Y=NM}g@{$mJ!FqSFx1IT?}v6UZ0ItFg= z2Qu(Kg!BtY|G`Z94&KAwh{*avrqmaa^`DBY zzD(ASBWqP~+7~lfKY^@o7p1<45S0i$Lrn6M$okJj)=v<9CNgEe1b{y*E&F9;{R@%x zB`Q0fDf?3ZK=cSAOD5|p$bw>nte?tceHB^XAv%&R^)tx&J0k0=c*#U{4PFs!5S8#)REAid}^Nc^Ub#II$L_<9kEi7XQTTu0*T90@$UpoZbMbR-DiM9@j{ zg!pY8hp%UF_#I^ZkAg;DE*p#A1;oD;5WiD`!|ws$k8}Xx(U+maHvsjoBvb~6-!I~j z8;n2Darpfb95CG!4g_$*i4)(-;((c_aQJ\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224231054-Binary.backup b/MikroNUC/20260224/20260224231054-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d40e55d3ee61b46fa64815619c5d727d5364ebc7 GIT binary patch literal 307416 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224231651-Binary.backup b/MikroNUC/20260224/20260224231651-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d0f6f30009a765aea83d387f546c1d6a092da6f3 GIT binary patch literal 307414 zcmeEv2{=_<`}aBn&M{;RrHsi?*k?XRDYFzQQz3LlWXu#vBBV(w8l^%>8Yn6nRT?x< zG#V;O%FuuY!gsB64ymV}r}zIo@B2RA_wQV;z1P|H+I#JL-^1_z-D~fYa%gYS{X#4d z2LOapj3T+AVSd3u6951x0015cK9~`0kr8bbe%qdi0sxP~|DhoU00`oS8%2ill!Zq! z5v~UY2M1+^?b!eT6JSro0B`^W#DP5#3jhuPfJOm;5(5J$aWDW-U;qz9zyNM=aBvV0 z1~h;S7|_55GW~*N`DY%$!Gnsx-Q)#V6B-;5?ib`^6v6TdF=F$4B!!n{EIct>8v}cy z6c|9s!+!7_sPSMxPie$Pcp5Pdm&c3<2p`#&5MCXJ8|la9hB*rl9w7r5g#BpF?4}iBC#RUN63joRw z0I&$a+Xqm=0DuqxfEXCyUlY8xr2v3f0KjqpzzV4EQ0-R$c@ z?E?T_R0dk5Jly6FjV=Iw4TAmR0ay&Tgu-3J;36CVJSPGGTpAaENC0q|Yyg%3fU89S zhynoDiUA-R031b9D8m@oZ5cdDJOF${TM4)Dz_4=20H6U9;P*d>ZlvB!{1v?+^7V$n zqmZZwmt?@=khunA9+~+=y`lV2Zz%swy-E72H%TW(7)>#}cpHJyfbaB1B$6BMOAwB_ z4FesXG_WUX4-Vj!)dvS~;^N}s9T>n@k#E%d7fpDpeJrm z6doS+2AVp5Ke>_GUh)gtZs}n0f35AP|0lIwAXokk7c{SqxZ!1ga>Erl!EAqSs6kXH zGuj|BfEyNO09D|J8lVbq(IGhn(f=C_5cu<-YQP~m1rfdm2=)`keHM>16d+*`#R_8& zTw{Sf5ypI07&kO>D1v^!1KiFIWCr>1m~1Ya=L5q%jCU~D!4C|EYQnY^f4d;Sq6Gn- zukOO&Ch$A_0Ivq@iLmF8&xCtGOn}Gm{|%!&$Cn*q#18P|28DYEhlKkD2ZcfK(mgmh zXd^sd&*0#onXvtVAH4*hO8@{H;W*&+puhkQ_Jb!dK?9&6heYvs6Lc-?Y^`QHdt18L zTIvns4k^Jo{W#v72tSV5cZY$e96pRJ5`_?k4`Xj;@%1RUp`%Rs?f`I{@Bor<91;_B zXE-=H&o;BS8qw7^I4nGf8OVkA#wRp5A_Ni2oGiRPC^?F-4FL#2*oN0i6}GDZ0OYUd zM!|?9xDhZG1r6X~Ph1)t3PfBe05q_nTqcL|qdsWZr&HKRW@I0cC82)dT*8k!VPL0$ zLH>#GBhJE$2ne7GI`Bt4JTffoP|xN^TAXI)h(4k$Cfh$E1R}=(HYYqdg6#|S5`L^l ztgV4PF$e(EVgNuG5V%?xsr?~ngt3nc01hVx01tkFK^F#ZJSqe(7C{LRh$J#RasZd( z9UkiE)rY=M10G6)?-57#fye)0AN0@rKs)|nAI#7Dz_EYd z2Mx^<`?b$dPR$Gnf-VQT4vx?*z%@tcW8tlo1~6q2I(3*vKu3W`^D~H{U<;Ew0P{yc zfTtG5`PU8baslA4H=yl_3jjcI1ep+YqbL~w z_*x|o07?M>=w_f#K`8@(8Y}R-;1&QVRRBz_`0|1&T^n^43@M3f* z1HPwr2LOje0N^29`@;YD!Tbuv&*ktd{NWcY05J371Pc8l%)nqK8VmsLxi&x3!<)i% zOciEg{214b5`-+c=JOl(R}MRB(XS4hZ*u{k00A73?061l30LH_;O#!$K_pX9FR`dG?!TH{cc-0B*vyI#dinpGk1{$#CHaPbmD%9nrQL(Y74XwiwYiAJMiS(Y71WwjI%) zF`}(IqOCKcJz+#!YeajLkfvE2!HwXCM~863qJ(ziEM#P$?s^K_(A0<8&>R;Ew?mY* zK-lgb92{f`+kJzBgB)QSQX_0(yMJ(SFhJObuwdwzXQTjdM%feBV4zF7fCeBL1Hc9h z0BIP3@lU`2)J68E)x? zi#`;)|351Mp&-U~4m67@z=tsv*2aBX}JM3g8t8D8Xnm;0{TcuUZE|$&gR-{M%)U{$DFo z89u8Q#0@tPvYvmxa54Wp;bQ+Y3M;e3FO@?p_IY~Rq} zpx}tGA^9%&+vO|r&y(+eNO`4wgTuo@f`=Ug>+g^)YD6T%!PxrG6R*gBMt$W%*ozG! zLIQ%BoFVPy{2dZTkCZS(EdOgItNBsetOJ0O_tKUC$26Q;p1ksN9d@Z0u8b^fFV6<|+Pg;}#2T;KrE z5Qp;yjKagCoe(&S0umySiV`sJqOb+oTQr}P;FC2lqvx}qE42Cb6b+yW)ADg}p#>K( z9fB-{hFBOk)Q=f}#QoCg3BPoD^uK(10wlddnVd+D5x*)l#8!C;g$37Mz@9in#0?SH zQh?8A@HvwCXg-;Z$3TG$)7g;n7m!(enx4;R$-yndq!vu$@z-E39~u${?~;Ix6MSGz z3Z4XhAonB%1T!XJZ}iA76XB2rvNQ+?_VF7g+#nkTKX7dzB;4RU1wP+CJP3XX1x{9h zoT5l%I0508$-?{sy~DWSaAFF-XaGO%{H0*+4(y4Lvw*W>Aej%VT(C;V*A7Sw3Ff~5 zJd_w718IFe?-M2D^#Gnv-@(CXK-xkB$MXvfgsvF!84+RJ&><={Rd`k?oS`<{XQOaC zS5WFPdMN;olz#VI>FN3$z{pxC=UXpg(+LAkio&+-U$n z&{$Hm*;?<+mz#|%bQLxA<9rsR-sx8~yrPm;UGMRVRCOAq4gf*Majfl|qwnSS=R0Iv zqpgkAfch=M>l>$qoU+V`(>C-FV6Ev!)LKK{zx`ojhQbSSWe^XDU^-r5*5B| z_{I%uT5tl@fQCRe&O4+tA{F|QY|>WkBd0#fnq{duz37ExdF77k9{DG4HV9-B<)zj( zbw-=g)T-Rn^N%M;!qMRD{rp3NXS-OyYQtaMELcSwzFFT4NCXZD`*lDuCuEXUmiIrS zx!Emv%>gF7-pz-Sbh}SX@!QtZD%5YOY-q;Rv*a?A3ZY!dZc{R-fK@PTkZ-Ylj+ zq==yU88Mm6A>MeXCJEQDJSZ~6)bo{+ukw5v6!OzD%44(?OddZeZit#o!hgB(N*Vw# zlud_(2J`#^_)Z3Xo(feMuAc&Xq9ULBhn54Ul#Lm-`~j4<(9ED3zNxMAT?vR@Aw=F1EncHb64$-=b-uqU38fJEkL{t_Nr=+0545&)D* z2q;ayOXQ#DlmyVg8iho#;6yr1NCXR(FTU)P^!53XcP8FGKAkD7X)tNC993;7_7}(SonQ z5N*I>w4mq%>p^(bDEJlLjG=C@MD$HJSb+Jy8+y1KN_e(EbVL838>}@8&W8S3H_W%) z(ENZl+zs=yZrC4m!wz@D{;ZqG54wpAcM~BBB>9JH6aBUuG&jLziT1!Mn;w z5qoAVS>Z zB%G1}Rc!}UQy{4JqzkvhRg|y|fkuZA9Kl_g!f8TqJPpEq;J?d-r61^f9t+!0mzF~P z1cK_zP#YTR1>sy@NInP;1NN>5KwHF~mN&nGNNMq(V$VHB9r2= zKoi3P*r{@Z1yd$DqpxXas@*!1G&}8L~se4MVtr-pH_*J&r*VFh`LD^j3kFmBCGU>Y8S5U9>l1(RH_t zS7#zpqImt}8Oa}|P$&@*fH1%Hv!fAtfuEHeIw2GcVGN=KH%rLNd@mk?I-)9Y#Y)3H zz7-O5%?Oo1AP77&bj>8fh_C;NAtazQM_xEe1YioprziJF3V{O#K+E6+c< zHD$4N(|z7mk>im%iW_3GR5M~bPtM4}J-&Z*sU$;`8#mKa?Tpf=f^(g^55nV?Ms0UX z@(o&`MVxhh_JvmWz~+$iOJvS}L48Pibih((J~2N+`QDxEb2d#ni@JA^KH1_HuC4Vh zHcmXh_ux#s*lAS`-T{$bduGu#X4Px91m0E{o4V-6z^&s79HpxsdRfHt?>l>IB+P3I zPMQ%POV+;m6o2pZ`uWpKR9bCyvqK&eunixNDZaN8pDlKvW2T8$NnB3arK37%_=rXh z8)1GIdy@Yw_Fx+4P+afWo#wsGX;M+SwDp+D9T!9mh9)hnGNQQR$2)whe;6qJ8=16& zGvwvOdmAh>9UKe0pB%yVL`UOtCMbWIH7W6eLFv7#1Ks6n^KYCA%v>7&a+_X(Y)Ny- zp1rs1Qnqhiw=txtKziJ{&H01ud(Xud*5sVu<$-^9FSXgJJC)r#J+H2q_k_i}e<#Rn z{d7HsyYH#84aNpfrGIjI@>up zI+;1mFe6f^M1+V~m=O#JKR{YHu}A{;8j^r16e2Cjp0lEpT+!W2PtBREb@MH6WTcb$ z4UkWxFgNcwIWa_W~rR(ns?ow@4tMu;cQ01`-NtsL+a!}ua0=h zJi15hvALTUXN+28mhM4O>5b_8hXNQg%OLxuq^1z=~&aQ8?zF%iG5UbUn);d>A zb#9J#hpn}9+~kysZu!iuqo-n8_cH4JB#Grm73bNd+n6uQzLpu=Qfu#g)O`Daa_q$= znfGTrzb*Szf5rB<79myBBmM8#*%nOjx+s;(2Kv)T=1SA2q9FZH&=y8ZB3N?sEfe}f4c+!dsysJ-Wja6s$Xa_Ol z&vo2V`UY6d)^t`^&S+^4YLV{kEtTsKRocM#19Ib&1lm|dL_ricNfad_B8EW?x6nxB zP#cB9E<${f2}9ozRI;*fczB4hkx?)^EaaPH2r(Vr3!O|B?!{)pTq*3E9ltXxn6KCn zp%o$K@Y2<=QxFD1+e6tyN+t{)CNzNbOUDR6OyDupu~dYNNQmMWCeJ`6_XnU+h?uB| zPrM`wh2TU*VFUfOg&y99`OYx;5H#&w$PL}Cep{D?_h0Cp7~@oM_!hUnEK@Xd%>#Ff zRUP(ruHJ{sD@sJv4c+bx&g|Kv|FAIQ@O8tPQy%1f2u{)af=r)~c>2=Gn9X97kFN5M zBy|86$760;&r7Sjp1hPEX!vxwR3%aw9bQ0rhm#Pa)f*p7Kh|ACv1su1^e6QRJ#F1?o3x}R=x1o# zRqox`QhV~ys_^6Q0&}+4eZF@#(R8=iHV8qXLmh^oi&%W-9nv?yJspwq+tdB_bVk2D z-Tw!k?khHD(-9(t$KbK46ds4iW>8opHj~a~)96$hi@~JOX)FqnMq|)O3<`}wppmI0 z9-B@eaS#@jNMSPg*!)ManvczY6r%;$oXw-KI0%)Z%*q8H*S-5w-Zsd-_?$>tvNr z)*KtRu$bP9UU$2u!CI_Qd|I35vTMuw3MV<`Zesb()fQonwTxdkIp1Q7){{fV@jFK8 zRgBAj<*9liD+>{4+`ES?ggKRu|ZH8TYjySw&tom1e# zUFRpioL_Lt+xpAx%PN?u_%>U@0zd2HPi+KXAC~g|P`ZP4%aOIcucbWW9Z6y`KDsB~ zd^js&7NlOD{#d&4J0;~q)$Mhj(f2-Yb@Rb6-z}daN{BGntDfq>T~+*Xf99EouZ*he z+&inn*M$|+%^!=zd_qT@>fcxN;K+vujq*2~WR|b7zO%LWq~Rplg0w=N6`xyoyT79C zE_nVV;CPbKE|W(S9HKW;?t5d~R;(=8fi@_S>3*1Y6&q&S5vsi>e|LLUfv?>5c~>^b z8RK)$TK0>Mrj_q}PR!|`w?5=_O1^s&WtwAwgr8>qf#q>eki}v$jO9Hr}CldZ!`ZpozZVI|83^~ zH8cN;)5sJ88DWu#WEz*nV6*9L3X9A`I5ZZ8gfIv^8YH+7I)h8)QkYZ{mq;TsI2;m_ z&14W5bS{U<$7w(EuESMjG{UbN|8kgynCp-6J_yc6{|XHPVI^9K9fWLY)Hem_Id&?* z!NeuVZz(rCSlyY+_6-V#lbX0;>Q07ch8nOM4dG2hp!!#o;};zC6@86^C{4JFb7(|Z zIG3Y7n;X6)IMn}_s?)2L24_H6wwh2EG7^^IAuOA!`cqi;eRWz*Fa`tR7z~7CFt9ND z4u+kFFzhsvfX)%XFbvl6!pIm0E7HqH;IKJ%1WiO;;M2zZR8j;TL>ulSA+P%9@)|lA zMt;msrN)O~bOJ&o5{L+mL~~b?A~GNZ6Mp@#kMFO%a&up7PH5T1x7QU`_4uP^KMOJy zD+|=|jQi+eaNPasT zRRq+f_C{F)B~P_ebMAPJ$@6OzBk5Mo$@rY-e8V|;j#d6=+dlzcU%?hG^41Np!3iHK zZgreaJJXa%vyS-q2W<9(QuY1=hc$1bO!nstvZ`n7TI&^B7-iX9Kkg{LUu#D1S^dkU zF4z*8ob@`55((_;&PGXEw3&zIvBDi@3-*URt*u^iL#qZn4RAGj<|iff=-_#c_&JY6 z_Z=9_pj96nXgc1r-M}hw%?oqTvvvLJWn2bmta+JYZ z(>*Ynd*sgX=F85!fw^3)uWztL=_$kc%#4~yon1Q&ME75BXWT8Q+r2|V2Tjo{GR=7T zxi!-zWsLRxljNS|w;4Mg(cjJe=r9?AFX%0XctYqwhQQZvpiBA~;%Uqm>$S|C| z_*X#^6!?WrteCvS2ze4zk#Pb9H~NQSB^V-;;r}u6+QV1!XTpU5jesD;ksKKvArR=p z9N9l-s0rvl&O1cId536mbOIU$R>*OcsG}~`;f_}ynkN<6aZ9Jh?(m$I%%+3t_ILvh zzW(;=-8W70+dov5*T1VNx*tQ+m7Qesm~rKd@t9)o{byr$<*?09M840TGHK(drr_#! zMfEiNw5HbZ>&nF&YgwGSxE#@UDawn|G^d^!kbk>MA?Cw#wba_@bFawySmWm2NLFy3 zeugx#JRoyWahLMhxv7->dAw_(K6M(rqS~ENmF1niX<-&! z#7jJAQs&-T0Ozi#2?#>-bFpFATTxw(1D+^7tnwVfue1CrH#(kjwj+7tarfggix zdc!PUEFZOxSERR$n8|lkbZ>DYLm0eSk~n)lJBLs^5!X@rdIh~H$4(+?2dPM3^u+9JES$m z0Gy||gyU@=+Rh&vw~5*^chjh@iLvACmCjsmx0qOc-pt!H-_o*s`^$N&vgWAGb3QPw zKb&n;G>40CnQv}rG1jj5t+tI@FIIJP?L_ODbK;LRo{Kv9#b@-h>+=#-rP=pivC8gy zyBNM+a77n~)n=R;H7WnS-PUnp)1@4HI^Gy1NPoquU!kc}^m+G#lV(;quXy%w=Y?JG zk70N>{s2w?z$=cxs*-SaD;fnB)Gm{%`iP1(+s>5?t8mlj?>@3(ij;2+J`fqYVeLBV z(eqLww->K(*&nPHuzxYD;$ij5P|0^bva2OC!!+iavz_a zCwIcafAB@4Jx_LS)%GLpN+((uZ(P@CJJ3K`oIP46eOwi@dE)8d93O2B&z6Sq5{AAi zQxcB0uk=Z(-8MJ8sC4^^)q` zX{Oz!areJ8`<2*O#~WoQ6x6USLoTl$G$557-Vjp~l5%9)m?~4hsTPaI=P5VFnkc?weXdM9(9b7I?+y+Vr7-3UVfEks|34C{e*6F5 z{{OfC|Ly<(EB^m$I>)6kNNffRA@VqMCX+zo5(#V)fk>n?*=!aNEXa;upxbyzgeJ>1oU(y0aYQ)-$Yzo&%F1_rBE*A zO5ZE63LW_n=)e65D;p9&DI*~;4mqrMJwtxocxC6A>WmL>Z&pi`F+Jv5FV8aA-I>akRB9Is>8VOIG+mk5I^8UA z%Hf(^1vhHcE{sK|jC??72fpg7%(o00W=$vjzSwAN!kNr7| z*vQ)~{qANFenUe*L9c(@9yG$>d0gbIKb1A7{=hxk?2fDTcWmR7P^YdXZRn|8eLSaw`T2?9i@vO{DpRO2Cl_*=n3ho`;spZ2sN{Z_DlRl&YSAQFMe zp;F0o9-V-Y2_!n3Mxygb3@(#QA|eD5iNqjrNlXHr%|?hs29?WW(AY#Ko5AH#X(R#% z;YXk!ScNE9}SNk(`a3X?^q(1<^O=Ea8eFFo_p@T)WHl!1eZ zQ#dn}=f@4;d{f{ROtPB{3B|8F@YU=qqxkpDvXlJRXW1DH59?o=X7>!%cN>rdv@k6F zV4B^AZ+XODoMxwuXbCvPal-@qMxeqOcSHmcP>Fh9cl!&m{`Hi*f82=wsz`LUqa5?) z!-g;DqF|5RGal`VZpuE1VY(_`vN`df(u88T+T!D0znzV1#`eprXBOKoA?msIm$t8K z(CiJZ*I{n${NSG09yF$O_2l|Qk9*;L{@xX<_sKY}wsz@06)~&g zs{Mf``}y>{Ws*d-yhljf(Pw2t%_95*@jCG;BNG^IBOKop#na3a_!a=1%PRM~a2{Op|JHp!wx$%ndxpN@9v> z{Kwd3#GY-H^HXE>JJa04IG?HEUfO$mcp`>zjM4e}eRI~PCi!*$+4Q^L=07y4`rqlW zew+Vq^Z&1z|5r#yWOE5@7Q*5&I7A+UOF)PW28qYw5(yLng~%qch#U^WX0kY30-H+b zQb+^_i%wz?C}a+cMdMNUknTrbcNo$Mr{(>6EQi#=p8|xxo}yPSWB>DKkOeO`gfEoE z#T^;==1B%Ah_Muzf**rHRRMsbHb(p1g>Qd^@68H?4oP_i(a6J~EV z+rYxiz>H`{v$Q5zQmm|~(f}X_u`N(&Wp) zF)q{mGwLaE?b;&&h4mlXGgiOGD(<@>_s;U*-JHr3Z=8`0OK*Q7zg%Y8vVBtxwbgKR z=@Po$hx&CJC8lqAp`EZt*-SqB-fIb)vpTEWMXyX-RVHDvf9CP-Q~f2*?!B%H?yYe= zpO$sjg6x;jMjNx$we7?Kg{D5+8EwZDWyM%|((Bd)wcXryi!*KFxy;2L?=g4l<22Vy zDGsR7dH?X3ad(T_jJTG?!KXdUY8NW!#=o>=o@g1M^iF%yzG2OT_`v~G@$>f9aSo%; zK6pdvu{o~Q7ErmyC$10$yPW?TDB#d;B(hw+A{WJZn5cjS+QcB zXZN0snj$V)yP6?gacAzQS2cQLw%P8leb03 z+%t3WR73rvQKlU{ucelH-80M9Uovb6zu|!EDvcj=-zzSx_nGC!({T}V2pW^|Dl4X} z#~juqIc}QD2rO-U{d~){mAKrATPtue-YXL=_DrApqK|!dK>#jqX}HV2gon4dYc=8x zDF^CzKX`fSb!Ez-Te?;SX3BX_9gcXMd~a`cqFHCjMGL=<<69@JyM}+hPgQce&*U+i zwapnhb6PfKzxpU~^vKP&a3B8vE%scMEX{j3D5Kw5QEzOJEFCHKzRyJeHdYj^#u@{;nfS!~6+NuVJ z16CfYHdWhhoibxoy3W+kSvu~hSN5oJlcefbKAXNbJz9Ecsh@?UA7$&C;K9r|2a~)9 zpDix#c)O_0d;9W%!(}_qsP#QLFMXpKdGYjPFLo_0cMbCC=Iw^1VztYRu72Dmw^eDu zB-eC9SLK7z{xzOhcl+s2*O%m?=jfdav+Tkc)GY6F-(1`E%Ix*~+~60hb|rb=5gi?W z-D0lD99iDh8)9kA(q)O$v{DT}pUU(7~ z#m(+yGpb9Xwkk$iOU<&}7-{CyRYDs_T^UERzxVd0nU*`@VQ6GuY7WamyZSEYwEf|& zb|RkEtxpWvNc_D+`7U?`BHhk5g%^8mg?82EE!`M5?p>F z1{HI4?XG>7Lnei8i`k+Xa>bejX3QVeBQ+;y(2=#s`*up0_(U zA0KnRI{T_<&*O;`7Oe4Dm+Moq^ORmv;^p!M)er6K(xRnEvS5>+-V&tWQRPT-_U$9N zIybGl{N>ye(%izPT#d%qR_;?R-xU1IIn#*|ROYEoE=t{U4{N-lgI>*@)!pg1;(ptA zH<z%k5ppZado;1&$Bi+P%(`EcNVJrv1lz zk4wi#L@m+Fi;ch?4%<~U;geBdaF&dS?y|t11(W75?j;%Z+ZMIt9CTMLIQG7TLYh^t zVUfFdZsAeZq3v<)kJC>-^8tzJk0mk|)_p8NR%losc0OfpMC&!E9<5!@b1EoIFQyvp z5j$GgW|)tB`Y39q^iH8rOEsp((VE-uy-2Nl+k2}QW|j&4><3nD2l^B@yvWG!)|zN@ z;gJbDZ;!jJmF=vOXFS9^#qRp%%cHw`!rEK_(bblk=-$?g2(*1t|>GEHC zOC%vYI+;x6^4Mf90bz3JG&+OBq7tZ7GKGUczJpCCaEVkdLLm~#BsLRaQK=**lS|@K zxFkVo>qkgxmnB{nxD4Rm*Z8z)lggmRm{`LkqknkvRc#MS4@WAD{1urb~8 z_B}7sdTh)F)G_514q9jC^fQyau1rieb*O4PNthNo=+^RirR)2NUHazYTccx@a^HPE zB*%;zMG{-VI-YEnrWjSX-Rq6c%ciSjZIRRO66E#GgLV5?Mm>CgNjukL+k=YHt_Kb& zoS3HXpCsr0rNn%EN?5kvz#(dC|NYXP8`UPqRbMLI&TL*mxeaj0T%E7(}EFEhHZ zjJr{;P zT94nd_+5$0z9(`nlrQT~Ea{ckcUx6?s8(h(Mfw1xa9yov+`iSX<))8~*u}oB8o9Am z?xFs5w6~UrqEV2itizTUlWtflP{eYN;CGCEJnR^^XKYDXaw`4thEZ67F zxpue)w=b_%RBIv=j}|{^cw$R+viHvkgeil+ImsulS*jm9nM$Giaw+li8Lz^ccj0|`g|-iWW!n#C&tJv zkK}6Zr0t&&EUqkPtuvRSr1$*e_5<#SqyFx$H6a_jbb_Cz6OOlV9YXc(A1If$C3Ah# z1MgkYGwz=MsLNh-RMqA1d0XO4vgcpdI+!qe^qtS-P~*ADy`P_`%<#E*(`yX;SG7fN z&`mm1-*F}FW~f%2M%TrLm9uOE%N#ar8# zUKqdpjL)-%FH>T7 zZ)qKWREl&mEFei#%j4FVH93#3ciy^_%#P`QrOJJO>kanS{Bbu;r^qd%=Im*^XrT38@wnx-B#>nUo_ji@3`M7XV)(Wv(~KP1^YJi#i&V+iDYk| zQ!JLRc%t&)T)EV!qrrq_1sYctj$3X0ZueN7V;=JDRaqix;g|O{DE1mon07=mOvcis zT6!!&GdAAKx#J_dMD3B2bLKSb6Ov~TO|n>v`+9l3-Jv_j6$UnFyH@+8q;9>>PG#}x z6V%;|lka+^b$r5}S34XXv7~HI<@2v zz2{$&6`LB91}|xfvzAwTV%AoSA)aqOCyB8*7hp0ybE`~RLS^cKmS;zc%`R*BS!Bva z-7&g$)y?B!Z1efVC}0xNxlZa(OpT&wWyF`1P^C8}OVIf%XIYrGeU$e-REV^Q?m2~5 zFS%`n9+lU6^%3d5TY`I{+^)stM}o?GMwQw3E!Jn{%-I>w?UJ$jaA6&mxMtQf$JIKk zk6m6IQfK6~{e7GD^DBenHlZ{n40N33&#XG1CG+6e9<$iRL5C7Mxo2(su-7L`xmcKcVeSg_MMmKO_tfo_r{=`&7ErMCN>3&&3vw;3mwywsw4S@2Mcnd;4WI>q+9IO*P-XMDa%<_q)5z zCofW4r`nu9xmmp6s+vwzlFVwA`D^DPE*nQP!}g%XZ0sCxt5!L3S~@C%I%ucFxy^g6 z1GxI9>Xf!;`;+g9zik{>FdHQ{&i9d~v+Gmdm(<-$eA^uC!f$sIOs-9sTzbiL)|u^D zD@nzTF=v<-$`TUd>T`mhKF*h+J>$_^&9A4>F0J#Ld(a_p)XBGYhfc7$L!co!WD6=ozrKT!{KJU;GE;c3A#yNI zyuv1I4X;%rWYgtcg`J|GM3;xGdA*(8a?woL`(;sj?ejIt`k06ZC^gYOO3e|ya89kL z5xwzdNq*6`FACg=bM>BjydZmBm=#A{$(5LEH(j>QC-)&|a| zebqTycSWW&6m7eHW>Pv@6x|;2^4+wRtUK?HT)L5#SpLasmD%iv{!M#ii$k1>W3S&S z4Y59cL9T9ndiSzzJIhxbnc*Kg>9Xa7ki#FmCu?PNM$gDpHF{WL{?2Nu_fl~krp=p} zU&$0I%A<4VK3-&ybuHumj`8&v`abu!nt$F`Sd7jTEnhW#nS@vSmBd@;GE64Dmzc7G-BBHSI>arYB6Rn> zS4SrwR#?a`)!6tpw9nVe8^4ag3^TV{J9pEG*DBYEyRW*-NYpqO^$euH_I?;+tYY6G zGRJev+zmGpXDL3}e-B$BGgEAb?#d;b7o;s!NEdOaDeAQ-)GaZ$aF$fh@+hM2#a-T( z_+T;xzdPr1T3E8{v7&of;`a4hIx;jab8gRnwsqRnaU2t3*z?J$MaitncdTcL;dQIu z`WG!%Oe+2oU8ue%?y`r<`7%bN$P+IjZM>3Li1@bYM;S9q|14AZZ8E=2X2d%RhGtX$ zZ#S8*(1-~AN#bxg3?h@j zVIo8di9}|T`O)`BuI$gFFU^W#ZDCEOT9{K9R04(nl*}K(%>Py7mH8h=UNW6-O);Ze z5zNdjeja&=Pfk2;eIxSyk2?HYBJao%{bl4WdRiQeYqjXTkGXp~&SyY5a?-9ak%Mbh z7ltP&Z8|=A&r;pzzHjRs-YOX_Um~yZ;*yG*;i*?WP~}fA6g??>w=D33$k8}&e=&(G1M&~Bo8r!Ixb}KQ0Got8 zl3k4sU3y=nJ5W}#Ro1>gaKGxM7kwPhF)r7MtRoHk%{D%h<2c1Gyt3Q$UQmTKHK5{+ z&C2Z>Cyv>Ea7;IdsaDPHH!x2cs2i_d;gC^9JezJft znUy$q?m%^%Yevnk)bxgqj&S)Ky-(7VJkry~);Se9{YvCDW}S|Iuz7p<-ecC4!F4_- zKROro{*NMW&a=fq*RQu7Q$NXgeOHwhWPI~nSJ##gqT^rH9eMRWF+RmQ{doSe1L_x- zwpmqmsG98c>-1Q;a`o)U9anlMn9`^2UESq*e`lu=I@Rs*ygTHed*vG!;p0`0SKVod zyC66H_;q64OIc~%M{^wpp0s#BzmQP9GsCL6#kJWu&(-F7Dw}6&e9TkD`*tAFS7Xx+ z<%?Ze=8UdW5AQf+hQytHrf{Z$w)o~v?58fG%f>7DeFfWc4&0q_H##wFwRN3aiuA|W zEBKN)g-|0+mRH*ss@q2QH|>3#+wl($n2xgDYpl<>^s=RS)qC%$`4c(~bG}?{I^4bZ z;fjHGQ$mjJn$c&}SjhkRj-O31`a|UXZ8E=22KB$*WWGjT7Lh{X(Afx;&0tWdG%l4w zrxLhi3X@79kjQj|Nh2c!CY?>7vbY?C&gBxA6dH?4C$h;*8i^<<;Qz>#{dwdi5iPCF zsg`C|bSrCwf{Ms;YP#{8?Dx4|xwI!6*axn`ncB zgF_X5+{3C}em{CtK^6w&&ocZM6X4JQJpH9QzXSm>B=P?U@aJZcJnW6vm+MYUHNLYU z-~Yn9N93dSB`?qJle?@>v43@0`cUTJw15vvz6G=DVwFc1RFXI5_HMTwH>qREdz;8ZPPyZJ z9~<7QQ?pezljxk5i%E&Uuq6lF$$gRb;;b9onVkys7zY z=@~Z3_m9_jd7QI!&Pl2%XFUonE_}E>tIqME+mp(b)|{8K%J1Ij+S+6B=5#_|npVZ- z)Z3TKi3?viUtGRXb#E$CKh+ACd`CKEm)(qY0k~p`9mg)x_uQ)9_54(PLEKTx3Xg)! z%3%72L_(X-eaoD?Bqe#tna@bsyV#oN*5=3b%%{yFwOwtUDl^S=E)u!0r9hvPw`xUg znFZ-Sw$=Eq3ZuybwC_Oi?yW&~)IQs7ercx+Cp6w^f)vHuJ%ZgI9egP}f3~`DM+)zZ zNcC-xY2$+n?qDy1CMpN;gmr-S--TV+)Cm<7+wA6eYupC`Dvw3!atx>dGONhteLC?gS ziG7T_j?E&K57e)HG}yj3Vow0G{^oVwf~A~{HSe4+*K9?^?~Yn{WPwCCSa*7f%fSm3 zdjr~x0(UYV#k{=Pl%H0%s*h(W5uGylbqb0H6H0)e$k?L zE@7j!+55c>Z(ofU@08XZ7qO-POQY4b!2&z)56--<@=nu?0kHO6TcTYc&E|7?Yk53i`Ib{{4zy|~fNwf$2oQpPKg%l0hwZNap(XFNqx;_hEf zB=nv$qJF&L(Ajh}PDQ$YiO~n?UF9bfNgH>rPA{WHw@whbtavhaZ;Y4eGG|e4{^jHg ziE6eN@?t`kZS=W)s`Tia{Kbh@AJq1(y0=r&;c6>h)?@MB<4*H+u8$H^Yf;RR0z3Au zVTf<&KSzwTMzXl965#equi*NU4S zpF@)MOn9#*RAr^l$2WH?oO(Nl)AAyIsfeRZ?u;EuWr%UVqeGn(fi=Y1H za{81!g;S)hwTY`9jJ-5zrAX*DG3DJ)VR?TkBOSw^U8NQ>93{@ zL@Gigk_l8ILLPqA$?)R{mLr~UpKV8wLu6pBUrZ8j78n-J4dpNchjx&VMB6$Ky)_df zInu@cWqxrC7uDRV@zlBea*4@XXO@(6_GhavPjC6^vc@l+$)Fo6QG=DkwBnRYGsV~K zwLW!hbjw7;^t-$84U=~n1*POp*fr+Dk=Jrg9#JNN(b;xclchIUN8;Wq*s-} zw8xRnezjvQ5>49k_nC*Uqv!L$A9@CVr(!+@&DyXZjUKRxWG7; z-{qI58un#8me{``TE7r0~M>b;j-59?1~yXNUFx!~ZJ zn|JG|y{KGZ(Hx~@mT4r@-*c+DA>qFC@#K=gmseEndsP!_lCCy3P&uj{C;LpDsRJ{u z6E!B6AuqMEj|{4ubD?!RFOUOQ((3i6dj22w-UUpO>?#ku*^im7o@vc!GUnf?BA?kgfAtE*cA>_z$Ymz@=HALpKX z&bjBFbMCpn`gOm5>0iJ2i;sNp*_VIox4z-?UYdIL(%M&j^c%nXW8Z)0+uyc&J^jS{ zKj(YDZ))oYzoGfg%ln`Dzu)@Y)LSlo!+ZZz?VCUH@t=6?kAL7x_WkOkXFoRc?4N$k zcTWA}o8SMj_D_D+6Q{o78&CY<*M04~zy1IHy|4Sl)+Y~t>2<&872NRO8jS(`2Wt8 zcnVNBH92*%IXg3RvfgU0`m58e6MoB|2wKx8S5MBY&CX6tH)m#Ma1>+mgn!bXo@kw1 zo1Ul#6V3X`)yY}D2&zoc+ucwzb82$t)P++MGqV>KX3w6b3p!m@9m&J?UAlqX5>~~h zWRzDf4~fM|A;i#w4+$Z<-R^idiPyq*@CIl=LWuue9R+>)l~-Q*W%c_z_T%~D9~DCUT_Hq62(ci9I3v){%auuGPMT5wpH%i>5MapcNM#?2?Z?-H_&SWQ*Q<8kp#J|X_5Yh-)B0@n z$6N5n=cqr92{H6iRfwU(Z&gp;hK7dmHG;3V<7*6GL*nJ5qJoRJTEUv%YiH9!92Hae zdIVpu!q*c5w=M8z)cO5tynGa2ufx}@5PFu(=M-MlN?shrixc=7E_wUQ|6|W4&GKF* zbg1%|Gn>>f@%1q1>mhs{6yoRu-QH?DY!b;o zE`(@pG`r(zkZc9XcoGwmP5_qw!YoRkcM2iiDHbQu(E%YU74h;Rysro`bakH)M~_s8 z&tATC{>qJK7Z=WsP}`4+myaH9w!`Ip~ys!1)af=ynbX0q&;Ha0Sm7Co4jH2$F_xO{o|_AGkI#Q=f^B_Z8V^ ziX292!0d9k7EHXYuh@Q5Y{(~T&ADLfXkV!VrqqGO@W#{q039?19_WPac98TJdB7Io zp8AVCXp5}-iN79<8AyOz$k{`t$g5j%#}A`g8u&?bqm~BQW2G|%nFhR#D2$?|3+i`F z&le{#LukDMx_B6L!IBlEaOlZ6&93;J-~tx}4Grx>!EF?LP5pL#>i9EPuRnG1`qi7) zj@NJ3>juWh@-Vi;G{dBa-EJJWL8}1l?FtzD|8}uB`H&DF+9wXb28AyWRAg?W$^L))}Dwjpgdq>iORiLd=TANif=D9}z=`_kDy&ZQuTn zh(jNG<&{?sd_)}jK4OlShbo6ZB8DmlG1NmJp~Yc9#qZ~eL$?Vns3i`Hm&q|h6<o1DM$wSYH5A7F!@JChg=-Ic5`bXa?4!k5P2VW8uw7oA6);@r>A1!t(&xu3wiV!r6 z{TR#Z0QUpWi9_FaKrlFm)gKtbJ{Nu>gfCRR9~93WzA9dN&sFiUZ@(&j{Ex1RUq5rr zK=I&nqJlnXsQb{-pmCbQ;DCS6%91Wo3= zdJbWze}gRaZwN#E8^TbxIpjQlY#*NU3{+?a4yv&p#xR9OC6R)Q$^(-ZYg08-^SPC$ zP0d4uAk^50K|eTiu{Lw!ME%`nqTlsnR|wVOqu274UXAV!J;+jIKf1#oXyjouGI63_ zo0&XSpSRr}zG_-{h`M!KIN-K$aOPrd>V&O|xz=OtuX?apb=v6_Br>?_1ASGeZLgrL z!BrpZt9r^#4p>81?Vp@Os0yM7wlFy-ZKq(U!8M26ng=H@)+Q#f>)38LTU|ffXs)em z*{@e($bP-bUZNFxandj>gp+tl4DAOX58X~{=lsmS=4TsNsN7QfOsPY<2q<&A-An_> zHQg(e4}8!ob{qJ-pcIlJspv&2o~!JW5N1-ztOstVwWXkWK#HS>XY05T7zv(^#jjbTbL}XjK!c8XA`%_JDYw@ZO-&c^hO0F{(mFOZQj!yCU#ItsT!;A`^~j= zt^8?y1^;8!K7bYLAaVd=r34CSV|4V@?|IK${@<&xuM4vAu$$G^!gdxUdR=%Li-5x4 zGwL_~i_~v-aT`4>#MAp1CqG-f{4pU`X)D;I?-qUk(}#rk;fI9yk%xr%(T9Ziv4;dS zQt{J5h|dy2{45Pwh|d;6yczpc!GQ+ul-_~wcb-%=6cTPs5R!-^2!RuSUc zD?)rng*0sOT@}`zzq=yD_f&-V-ii?aQ$>h>ToK~?DnfjJMTn1Ag!qAq5TB?B@sBD( z{7^-Re^L?RpH_tU;ffGHQW4@uD?4@HD8&C#5#q-yLj124A%5;bA%3DF z#7|a)_!ku+e*QrreySqGFFq*5Pghup`PV{-|4j(t3nBia5aN({Sv)9Srrr7C0Wl;d zK?PIzn#R`*zD{80ds2v@gQxIo7GLv19D4LPG0o5yoJJ{Zxv|xLmk>jf#HkBH488V@ z5Qj!9LYx(1Xg?_{=TQGV=n#MjgKdIn$b!Pj#_480QK*UwbMkoeh(7<%RX_%p%RHok5HiXHs=0KSl1 z0-Qf25YU2{6$G>(8`cmMn<4Q<`1;%U`aAggkPt&(VEN`DA%-3x74Qh&z8Z}`28@wK z;0YmyTBEAn%RuuLd|k!YaUqT#45Mx@Bgs*NV*3_+(e`~2zdU>)+!PD25aQYaaTK-` zle6oY{fm>#L(EUiTg+#l;i|u0uA-U#G;-Cxa<1C{H=L_TcoAz6SGn9l?BcKwu@f;C zu^2HMu^llW`0;_bmvwtt^f!C4s{Bn_toE0(6)gmR!#S&Dy?SshPPYA|1%`Re*|^gQ zqD;nXGTR7b(rX9zwTSguAz;W%X2z4amxa+f{jb&Fm*|3bA)q{nC!uUB{pvNa^JCG* zCizfBh?hufI8qTKhZiU1D=#Bf^>Yta#K^;olW%?H%!&LVNQTGRF zk4tqAABNZB(BZ>}2iN_c#~yzW{r(8*{s`*sN8Rsv?D2!B`#q06en9p67iO?&b0cW= z+Cc&=!d(0J)nH-f`eF6^2_eKcs^19j{kZxK!@>8e-`G*;-+#Uz?Jz>dD&o+8TM%Nr zA`XdHZEj3d#G#kwhQwq=9NPYat*`@K39vr?ejyJ1!Da)Pt2KFb)VfPq!=lmUcb|YwR$_sHK8AWo5@JEo# zx%GCu>bK>3kX?$>>}Iz$FRRWUK<4W;z+A>}x4EH@4}cBREdTIJX`0F2H~J~TIH_S| zxB;dCVP00to&xIEl)U)feuy11sFj1cXEK;8CxgW@63`Ew>3?KlF*o%kz~-lZtQ_7w zPW^qN^>u)f2q-rZuowEUuxP6T{I~ev{{{9HR3JcMeK-P%^(tikJ8}r3049i6JqSu0 z&pO?;biCLR8)$1iXh8w2NIb+JyB1=6P5kki`&f z!*hh4G^`C67YTpb6T&|>#Ct+)2M@mn8$4|6Pm z#y9Q;92o(_>d5Xem?rz@L^?b0GW}?Z2tivj!tZ3S$A$6El-WL!u1gSj5XuVxW3|(7aZJA zc5!m7nY14eqAn_5_5E-ElV|?(2Y>0~L!a~Q$A0H0-ubVBKYiD~`=OJ|KPtcL#+U!& z@ujc%(;xWof!S{#z46RH|H*p>FBbUwFf4D?hAkG4d43p zZ|VN&w|&!p`u#V5)6#ET`Y%8K8yA)?{^^tRU;8y@j(>6c)xY<9zx2<3?RREwuYdi= ze^LO6;Q^P~w()`u0_}l;Tzn*;K<$w512aX_H$QAE~e8boL_HRbN z{m7sF*$+SVdk?(+D`yYl#m0dXum9wqeDGU-;4Q!Z7aQOE>*v1iqhB_EL{DNGWKds? z3m!59AN>D0EDuS!gzKB~nnET%N&zZGXDK_#tPC9B4DCk^W2kXuMxdtr3gBHNHmU*_8;PZ zxXy4+?5TaiK*Mr$9~yd1Gl;sijrMk@*4;=}Ypv$i`w!tc`Tf!`eplFR$GsLvd%qAz z-@F)ZCh?VzcMW}SYR+aa>$*8!$KTdd!ZdZAjBK0WPY|ESpQ#p z_VU%6=Pq1cxPHEN=~``})dJ*%?7KF;&u#o|4`?4Re?Ha5u^t-8hxh-91zWIB=~IFH zfZKTW;17OU8$XzD{DYrr<8O8+^Z~c=w?FXre%x*SQ^om%ZsVhm{Gr}4)8{UYKZ2ci zkj8Dq?KEk}qSZNs>*0g{zl`ICJ_LmbaYT=?IHN7L-fDv@UM&P7dk(=-4Cyxi09*xg z*mjFUh*!d51@FZXb7l+|0d*x#l@sI*IApD3O~bYr}?zsuATPKt2aVrkKHN&M~wk>Y^Oj`!f7jL`#W+nFx%Glk9umYqLx_}HzvZZGR=z5rhu_mXC?LLgFcf<0*#VJ3(*1xO7NCK5xz z3!3-gs-}Q3S=GfyXw0Cyb-C>)Q5daDZ#k-!ewL$U1%hl)KTAn-IePZ4A0jpM5Jqb; znqM~k%Z5B|{y09MAc5atpz#~U@*qE-M?R4aqpwkzL#8N81PaOXcNh^>U0j)wXikdH zh{!=b4bQ;tt>~t}E1HqlS=m$s=ai-q1h<1`FAG#x4e!>ixvrn2fn4_VujeIA{jhhB zfEl<9Sl-CIyd#&rl@)JZE;En?0G_A5Oy3p?jR0-o1ECh5S){;B1r?h|Z2*|(zVD#( zV-g<(xi^LhRGQ*3>5V06bGcskK$ml^SXv>mM(o~Snu;D%JUj&+J~obqrQd4tBvq*@ z8YC{7%i=Ukq~RvwU8(_g;li>RM_CYMX+v?UW<7`ZsIRIcI#u2IBZuz-rIIvvWE|Ck zB#9Fx3)dz61r9lX{rc7GlKG^J{O=q&d@R@Zz%Gk(%mh`OJ(^L%Pe0|%OEAZ=Jc~g@ z#tDS8vij0wnz`(+Fs>?;ioO9{xl+>V-Uc+FL1F>TpgD=hl8qMzCEVx_;#6sA_O4WW zjPaqEseoq&OAB8uG3M{wy;X&MEtWL))1+C#My3a_(H&a63j+RZ-08N1EI5ks9XTw) zkb^K=SmS97eam{du0|s@lBvx>Yz`$>^EnmVjhIoG*qp(PBW9EHNdo!6{fuXE+#X*G zvgU^Db=$GuYU~85>?Q5SaFv}7H|g=sqzyqc?zzh#i5~6-Q*A((y);M~`TA*)$gZEJ z+i}v$zq;n9sZ5h*4WV>J!ImF{l(aar_W|?()dws@*ex)#0t~W8K}MB_tG2q;e7G(N zOUP5(E$urWKB$%0hg~Ih!qsA1-}MpFVxRxyM@Wl>(hax9SC^}>2cg1FK!^R#19s(0 zdJ&X~r-MY^nxnPBumW~6&}?X^TS1bBakL`6VGjc|3Z81e=Vl zuyUU5rCHqJW+2U-hf3v?QtQ}Q1Eg9EsuPS|`_fM`1GucB@QTz+M|G0c0aN;X)N-1d z$~SeT*Ws5@uOq9|`Ipy&te0RAN6=chCWmj$wS!1juk<=AvLWlNDbrZckXQHaP*H`8 zAO)1&u(`=F4p-^m!V{=JB2`;US+cS+FN<9O>S7-ZPp(Ncg~t6PTe%~Hb{b%{QuIqB z=jp8yFld$Nlu5ME9u=uOh3*_VJeLp-WYyq;Mrb!Dc|wr4s_vxTov5TY;>ihGw_O={ ztD0|@3V>wt^mUKjN$zfPaCc8DdZ#(ZydTR?eB2EpXI7M|M4&6>pt`hpO`eT=?UsyU ztixI2H?bWf_gm1CSC=FL%%h+!*OIuSSxlx`5=QHD@;N>9tLZ}2QVjOom|E$u4nQZ7 z+!6gAl}++hw&V3w6@vm|7$8T73W09pa+t>T#Dt;Al0w8&w#{ZcP6N$?OgY{Ni3q2R z8m49eOZa;cVEus=#g=W`(gbe{|XKwt>*Mm;H704{<1@nakSw0Vc zdu~NOAE^pTcT?)|1k~fXW2)`z0hUSbK{ZVBSG`{7um+T3#q{8)Nax1KlQ4?o1%rhgHrEz+@U1QO6Ug>Vs<72uH5(-ZR zJ5T%VUa*wK3G{GO)LXHI&dqM??DfkRc&Pc8Ia3GMf-JC)2}l;u?wTPR(!-Q^@`V>z z%CE+8o0b#VppKLP*F-pZXWmle6iGTMkB!6a6Rw3#KMRb50zc$xFKlOFRLhcHn$=Q_ zt3gVR9)PR&cvWRKyP349$#fi!quS@4AL|AkPqxyGRTD44;c~33Z#W`Z*PB)3WIG@%)v!f31%0%QmX?VfJ^x9g}Z_TXM>ytAl zrzYz46HVWrp7JLqC;Z9D)~R6jWWByNy|y~rTst*0xmKU_Pu5TQ{!DA;#EBCI%{fbo z%PH8mxPR*!TH&GnOiC)V`t)1p!gY^vhfn@BA|lWv@7Ukb+}a5;5e9+*j@8sb&0f2dZvC~ z3AW{mwl69^C^2&?17qq)Dty>lqM|KeI8)`u#%L|2GX29#SdiyPkH}KhHWXJ<*P1lc zPL=Ug)k0At1$J3yKQ!#+=>j_+)qpa&cq5WSY#Z3{NI$J@L5|9m+G(%lXFl(~)Td;= z%w)`EaWiSJ$y;Pm(7o_$xzdMh&_Mq;YR!cfA^ z%&Ek+C2#Z0tfyQ{f<9jE7Zx`z*3QIP`HL&DTIIqx(qaG~O$PVMdp(2}eund!L4%0* zUOBH!`VJB?3mw+(6sH#?3~di;&e9I!OKm&MHsW4ZYbNbaj|?J0A$wNU>W^5Gst(8F z&osaiaQ=3fLaZAu9`Lx7xsQ?LaB3*waZH(|O{3+tWf?K|nbI7086);Z@4d&4CTSDe z(9<}0y_~#rIXVX2B#5#GoM##iFiuXE?8$-FU+of{GPfjet8*H(Sx(utrlHX8H3tCJ zJC%i=<*DnAqd9PQ-^1hta%wfCHzu72Tm>6WUJsu+^61lK*SPsOLwmM*g{S zvr=a;KJozPTXCTrEhDbx@U-8ar)9fA9dIwX&}>-TqF!g!Hajvhq6+pk2OQ_xd&gVf zT23XW%N~!+57$m>4FII6uryNIr6mOoPa0%AIQvRNQ#&n>St=v#$r;A_IN2;ZL7MvO zL1TDKVvVetDCMSg*AHkC=8t`cj>#uVoy_L*1g7l;(hmlHUQlHyoGc4B<@LCi z1Ze)gM-x-y9mKw6;bsjd zX@Vq9RYYD&rXP%GDafQRTVWD3vpCt2@F!rmxfQmc?a;9v7FjKscKv36N(-%)^kpY( zCh^ia+4Pf^0c1Pe499f01P`8!FZxl>Z_h39>5X$?x(N^@&QQ<+3twJeSghf>+zNep ze7qH=o1`IRJKdl`aU_zyYaRb~Ee$^qG$!kdGHu6MBk?=OjnTdpCej-aLk>ld4WSse zqB}`W&u~rZagLIAmZi4LVi~~>5U$By3XB}@b=MQW71R)*eq1d_M-GpNQ5Ga?elr-~ z4%b2*zD`?A6~fL2ktzVxZEzCmSBq5S<*Gm>QL>B*X(cgA=z~K_a)qBxna|N_L(T^@~q_ zK$;0jrJoSlcHwDJXVuc6>nDB|NKaRVsfmsnjL91tumpuE0pejkxBabP(v*-Jekxak zAd;iZ{ay2$-WaNyVV-WB9GjSgaY+*+ z2vAWAeq#JoMKk_dob)<*hT95*?JVww&9UxA_nlc|vOYOIIYstX9an{%Okox@GuXVs zsPVk?{G^jJxs-fR=EStSo9h2~w@;mT_HKow*9p7nYT(^*w#inD)g;1z8Ip4iLM5L( zUiVyh_u-&brYr@kR64l^fGso59+V%L1)!=2Q?=}eqhnQf3Y_X>Op)wd?!>L2K@&}$ zV)cQa+1SW6&*dpVqio!EI<5h!*=MyJ5Mxny({nqrHeAT8JvLx>>8@g|uyUTfJsM`c zzQFQ3Ca*@)m(%s>QMj65zx6X(eKh_${*H1&g=t18#M+d0gJ!rE2CW=PAN8P`6TaA5 zLz>7NAJ>}5BU%$#SVU&BUe{GU-nPuXXaslC5j$7qIK&6EdR;_R;t#40HRA_gliy9{ z_?i{VIjJk)B`e!nSDn*;)44)g6ZI^j_D(mGtY4$**|@utgzFob9Bz)t$$EXJHd&uM z!P_{=f$s0pu9MU3=0QCrR8k{wMzvst+?mZ4X$4zhGpK{iGvDRu1TvHa$fiWGuXj~VM2o1_@Ickw43E7})} z776M}89up1dUD@}iE1Bk#ym<5-;0TqHkyQSxa4TH%&@17{5Gaz;LtP)s&Q$0zVAU9 zQIvDn>0S_I=k3AZOXOMDLBfloP(8rrH{ufoP1*$Ogi$J(N4>uiu@IEf!egb(9Ta;u?? zi3QVMDeIF{jdLmE7?YnCPZ9*N)Bch=6a|UkSn)91P`6SF)nTJJ$&aJM!^2eorYqJ? zdwEx-A2m1PB=ts=i!{xG7I{e#US&RaX@vZp-iUlrdbIf7cLNRS`R%qhBH#A5900eZ zmV@r7)ks|H9E=y*IYDL#jx z3!UVAJbk4gxX^9Np>8g*jaW4z_uM#sR0nR@0CngLqu)iGZweuDMHg{l?QvUkHZ`u> zRJCcTAILu1kP|MlZOF<}+zGM`AUsUvb`nSH5=Lmb6ZaB#4pNGH#E^{Zfe!&tgoJ*| zlXxAzYcy%jhO;kf6x&bQkfg@rr&%hF)~>c&#QDQsp8Fet+3U?gBotJOQ=2(R~G zhFa2zOdQTo{6#fvNyf7@nNJLeij%HJ=eLl|#>-E>_7LlA4LR?yeyCD7JoJAp`b(L!^hRKvHAAACPoQ25}Bd2?r@+%Z#nLmEg=1bWD>;~d>@=h2b`M!XJ_Wj@7@!;sCFI#Z!Fl2=Yow1x z`zex*e_MXLG0_@46GXB7b8$KL$u@y__HezI_!L@(0J61S)WjdItcm6G6z^PIZ0<#F z5NX($#F9}DNOFS_sQ72KF|Z+ruKlH?oZjM41H88&^UPwpF86{04%aoxjT1JkBcn(s z8Ix7h?3jx8)k>v`{xtxgD_GRwp`Ui|NCfLcq$r(rssQ4QP=*P$gORp5?*O^05rXsf>l)LU52+ zx#13z4N7X9+{|vA=Qiry8^2A}5jR;_Gk6Yj9(LEBGKOPlmyT~C^fd}(fRtaPT8|Rf zMe(-0bi5<8FbP^?V`KD3JMg!{XnjnMj4Vet=oIjF*lx>JgnFv@_0^yqZ;$dEhpCL> zq~o{8RDc-_gY(KqIcqF~uX8MetT6C;?-~fjv9BWE|Uvi1miSkYn$(-4IR=+JFQ2PMl_#(N?e) zMnOx4CidKknJ>b^n7NDTFTa4I@KSGWExau$##q0lv}sGdPWm*0jCZtbwLNlQZU`tv z&D#QMsZB3M3M^d!!#fwO_SThVKWFP)!_jYk$1(WFw5%>xVq-Czz?%w#Xb1vqxN6(E zx)mfz*uv2*Lzc9k8tDfI2QSdi)ocUdnY`Y~VfbT5B_(YcCE*FDUn0|97tz}zvgt>d zsa^_Gd@8qtcANZEmt+eb)J!G;uiGu&w2x8M8V8h)phGRz+VT22Qb$6aAZJ+GVDUG~z45>rouCsZ zJM1M@mOky^zsY{y+>r$3i7WTEK(6XW&e82B(la-Y;H7;{QOXyCC`kPFjaZ#yFcy1n z-X1n^OP*~qd189XbUZkW#v>>2v6cnxU_J3Ww&xq_$&Gk3h%U9HcWP?3e(J=jsmbZN zg@ub#&$cEu)}FpTxp<;`abf-3Qzt%uYvXD#{qEV5(N5gmcE_ljI=kU#XsI?)uTPzr znwYB3)=x}f5Z?66^mKh{dU^)+j>(%T96KQ~c^X7?s>lTI(^Fr2becSCVEOeV?sYM@ z8o9dT8yiXBx6t)eU3UOGfF5;wV4z$Edkbvl6B*fXJOopvg4ue9eAN+ZA z1i;1#9m%AfRyrmx0*X}n?RLD4rl>AieArWx$~5fs+L<2(aW8G}jP>K35tZIhy^~hv zpa_ai5sCb4W@2)B`qbp9`bmB;Q9pHZ_Qa`EljMxWGIk7AXC`N-PtKg2nkH8n$6K$QJU1bYnFx5)}-to)2`#z}|@0*V~pB zT4Cz1wgZ{&bXMbbib;3LICXI8c9}jCW*bYYPC@YAP`;3}aXU_~Qch=G#KM0rfDimq z7wMAD@eOU(pAmMqrY)n#TN}AENN&{&e!GoOXIt0rhGStjT-zColXa?h;qb<*Sd zz%xif=?I1NsN_~2mEB_B9IQQxirnhes2Rwb20F%Hek#2WkSfp-l7Rq+ zaeplf5Mx7D&f#!9ijyFf&#lEtGhk#qM;xC2AS5VP23!uR!vB7I+uuo5hq}K}sHzbO zfw-5c4mqw#;YilXn=Nfl#u4kjK$)H5bHNru2QNjds=wZ|#|Q zFI}TlgnZGMJ>$oR>2qwBtBUg?)l01)%EAn5b{+%VJ{^pw6J%qZsMj20st(ACQmnBQ zM6EMni!tuRy zGwhBO+tc-3ZF*_xN%>T;(+_64fyZw5j{SN7z$h`Wisr2%R8)yxwybuCq1P5U2yj4W zD6;5BxzQkQ?Od-l2tIn{j-D_Kw=n5moakee_LP222gtS5VQ%O{evv@Y&W6NSK-U^bozvIc3QMiiltIZd^_m(!gygb$#AEU5J%J!xs z|CCNpmQk%ATy-q&#zpSpX+KE`*t-w3P?Mc^CK(%!tQ1nK@Zk0CP2mrbEo!4<;`y`( zP-DwAJPxp1Qg968oM+U`Z{9zudZpZG3QuseurE}u`C&U~&9R^Sd_q=CeFlV+k=U$b ztze7R;fAcLpP;Y&dD>R6b)7SpsAB3blq{L9-EcnOK##JtT)%mRj`r9CJ^knhHSdai zMeZ8=>dzeVaq5v#NI2>PcmQ6v!&bH-JASemBy!nvfG)>59lN2ES;u4=t|Ja@J0RJE z-QbQgf7o@I?NWLH-`>Ddt3w!IF5~w{_1Rq*j+M=Kre5!)+DP~~x0tuE{qAq;kiy6N z42Ph3*KD}&Uw#dl4JQ}Bip+*c5(%^6emB1GNX|Y3qhbCDOoq?>_TC~571sg|2p2`s z%6noghK3jR7$!J5fyPWEVSkw5s5L>G0IT!2!|du)X6;e_28M{N?^UBaCYC{Dbj%r$G_ZJe{FM{u83)dS2Zcc{I0#|&4kg}3iP4!-EwM3My_fuU_s zh??z$OK^mmc}g;)4`A=|1&`q^vg4=H6{Q?Rz@SDN(=sR{Z?(nLLW$VYD!$^YW)NaQ z=a^F%+npV`vG~0 zirWgUVCzimCmaN$&o<<9Kds_D9d2-Y(qh`waj2O^FN!5=6?OV~N@J!plZ3sv$SB+(g)FSKF;V zl$IXm*6=x|6leGsgN$GF;re{q^t-`@IJq9IpTF%?!OBYxc<0&KcHl?Y_Tl7P@wr-G zH6UjJZ5dF{SB zcV+21r9lrP#3kqkFQp_kb|T7%t(d?*JnO@;Ut0cpkOtY6EYH2*_5nRnw%0-M;bjRR zi<{>{7v^MgVi3IGRCQkKQ)}gKfh!fYsmZ`d2S)@r%o4#jojvWl(AbC9bA(6Y zu$WXczf9Vo9=4i>DJ`(bm8o)}L2a^eRL+`g9~KoA`=+oaNLkelC=YeDj?55M)vbz{ z=f6f&(n|*HEH5M4En|1W>M+|l13@aLPAsTEryW6|{?Uf4=D^lF8tlT6?=9J3qg~W$ zm>o*KD>~Awx@zPbyCWrqI5noQ-IX2xc4LM@csN}&_P^+-6dCZDFl4E2U1srI0bCn# zBjMUH$3a;8*&RI!EefwH3FB~;tJY3?YD}t&QXo|~s^8hO^LA`ldkf~%5fmpleCe^C#&AU>_obA?m7rc@C??H(s+mR6u<(7hb z#|}@L>c^XxxAH3jUr}*y*x@EE%#Mg|Lvm$(n9;mXQdcJ}bs34oEuY_3MqOx~xgD+1 z2n-LE?1#aN%ItefR*MDbzyt}K+^VX=!WoD>6n!n|SYrc()*EPRi0V=GcRmp8!{_tq$1# zB6+?o>dGHo7ItYD4mn)a71c@I79AGSN)}bf4_J*YUsI_QyHqPAOxKCN^Wqc9{%u}% zU}KlIzsB5ee${o2m0=%Zl5}#6egl9 zG|dY?Zv{zoFmd1&`lrD-Z_5^8P9s4EaJvE*`Bx)GTLm!}lroAst)2E@3D;V-TiRL$ z`>G_$T&Sne=_7A5?5mlQL9xd9Bd8 zD#BlxSBhS~JjwPP|cfzbI|JPxGV0MI~jxhr>yK|g;q$m8jvE3uqbWnLdq>R79TYPuC*X% zn9i*g%7e{!>_CWFTeHzXG%55cN(A#UzWT=2qo=x#E4hj<+-1}$Z&eoOp}Q2jkMn9l z?oFRopx<5#SKDEe19XEF${293-&*sUo^kiBb{OU#x)%-FmU6afD|YpjDdx%D7f&s* z_po-VqDxVyOEMtpbjc!=GkGZEg_RNgdn#3d#tynrH=#h;wd0cBlW|IEF6TTOM9HBo z%MmuQDqBV&%egv6K3oNuwbLFJB$#TEnUzn7n=Bi}4iRIBqI2GW>U8dl8ro~`xGT+X zQd-!%bbgjgx_!HqOS+cQd(ux@STg2{7;*6knL%Q4j<)_T+mxfTSQ#sasjJ<|lyBi~ z-4efH{>(CsYGwk;rw)ZJ^YzafZju=*l)~gPiuT&R%ffwq^pOT|$TbWi3X6sApCQp> zEFa-;Rq-XRrfMTheh<_M5L7h~iAVJa6=ls?gs5NII^RbsR>EM^l=H=H@Y4&PYOM&J zWo4K4^a7{%{bs#X4-C%joEJn0aHf2p0m$Fkf>w_E)Zf0|>^$G)5@xs$h4MXw z*_k8^)+jcrRN%M-jCoNjy(d-P6h!dpZQKg%rK}&(mP~5us=CfVt%0SAu*jOC6m?oZ z%L~IC3vCQ5Y?;@(PX}{c;Pz^$TXHUmTDTOn9YpKdM&p*O>VkNg@!f3`az#$oHy-%{+WM)8 zdVxYV;L!Gm%Jq;F%iK${Uc?r{h)J(-ZqePwX5A5;dy z+1ur$lE0M8tEvDWlV0sK>um%mJBpZpc>FhZy1`Xkj-x5M$`g~@TwD$!fTPruvJwh` zSkYXBGLg!v>O}#o+9vm)dV_3uI5d(ogcufoD%criM2AsBb#LcN84}cOjaaDo`o{is zf>xS5fbfUO>QljvLFE(35O?R91U3$({5DNNA>JlrRT`c+Wn}DQ+ZbE^5jXTM2ZoxHH*{BltvqS?I2?w(Bk-*JbLsfMQrQf zSWa|;bPLGFarCH@s)M43p3Jf?Ma^hFQ}SZbZ<4SmU*Me>A)^@Q<#4*_H|bDeduO55 z38OI0f`mfhtT=SsVn&MQ(ktNDbjNRQ1yL(bQo22WgD$i}F{m3^1^l2etdIE>lS~%v z_Kx%&xI8w1S|h&cqHL(ryLe-Xk5pct_DqIQ^hdV3JbhUM;5H{wVH2PZu0q^~$?ooE z(c=R~I%otRl_1Hn2O3gmDgQKK3MA+z=mf!l?5aR656u0-W*iv~a&)9#f$oZy&SCG4B1MPI22EqK1HPaX9mvTbyFFNb<)v#XT}(@*XGnttq3&urn7~<#8ag4e zbwlDv;9E2lxCMD;YRKgpw;CRWsN9`gspGrwkdDKm4@cO|lm*yXal!rq_b8Mc))aZa znDKN-54lXZhx=#~10M5qq)CYoaOc(WdnkUof9TDu(j@kgEBFBiM@%t`P0sT}F`IX# zt~H&(<9}%Knk)_Av>3TR`nn5l41sClU@gqDTj?5EU`c3dwH9%HU~g@8u7JmKEkc`dUL4W zFX1XB4lYtp)aFLraja#3-|mnIUBA_qBYwzRe{6f9q3UZP^+FHtzl@-?r$Xx*DVjl{}Zj)$=0;7{`MNgw~ zYtp#Y?v{W-tBN?Csn+dLk-AgJaiy0{o>rmyW)A5n!)(XF`9vPAI2Sc$YJiaW^#VW6UCVWT?tU03a|>eN8D45`C(DlX7olrDtOC} znLxvvs3fDk~L;0^rE9% z8}^nb&fFq@Cbd*MU7dgo>Chwki30Tw#ay`LeK}qybDYMgB=kt{9ZI)9jqC}KYHW2= zGs@}-580sVMLF!fcbGGVyg*vW3$*gSfDAb!%T+IbeFNdkRBlL*s%Wz>lBOz6=5oBw zxGHwokREm5)=@gxZgl{Tr!Lu{e(-?xIO<1pAiXnN*~{_zJPUjSv!`Avd66Fw>@Ykc z3Xx*!%Ux}xK4+7&Dyktf9JRuQJnGgfx^WMg7cm~W z*7nm4zK&9^;wAvsoa=?SiGWjg2Xud)f!(n{$g|fka~?{%l2Qj@u}ENi^3vrHjvDZ80Fv4!rOi!qQP#a_UZ@1~Kz6T=b! z$xfnLM?i3XP^XFGYH2dEXiR#?DQA{RY-lZ23R>49sU;3O&y_qYm?8CANCd`$oOCFM zsPAv=r}J0gl#QJeaU%~H50q}E>P2*ui7Ppg`YYSGD`v*z(nj2Cw~$#l-gGeII73OK z7FkH$PwwzLIel|Z*+v~fhgtg+@~qk$dTrrCIa;uZbPc; zk_$eJ@^mRpdqHyc3a_SqlJ?!PjtSwBgj5#3q1tKh>=hG(>e_M2X}Y=LhY=lgET`rW z`CFTDr;CeWMM@Mjgey=SuW_W{2GoE zzuka$0O}Y8ujZ}`4L|k>P(6>rI?@{qy4U`jI!Tq4GPod2-Uqzl!y4qa}q^@$jKF3ZK6+I+HdbwZ-cAI;EY@f^m;&7%nngu*rvR z!Ve(dapQey9LeG5bF6a*)-W@j(z)1g5CzKJXb>N@7V>4`6qaS0!WHlR8aF;wmOllO z=1+;o)L_1!=-tIGxAXYa$=*9|RsM2{(5e~uFQ=)nOr$iYd>y+*O75n^Jiq5ptd`-3 z1m&KTk6l!wq6VCUe9&b!FAjU}rRCqu?wItRy;ZNxt~>#Ih}z8zoDOGY+l$EYj>|N| zWiY+SsMU5h`ni*}N1Y)RovFY>N7T6+1SG7x`;d$dAah!cUYd)Ni>ROacCfDy!vO9< z|1gag^p8b9L&`c6%w`N9+Nhz|%A9JDU;LFF1=xYHVE}H19q1cX?l(^I7j2rSbcr4R zNs4IQv8QQMJayPdc2-p9`1VRHI~Zzlomz`~krP>=QE3G#lBvyf45ws2~Bz&~Em!x_>Wc@K^SE?T|udlS>?r zJb@L0ngE%(#&;*03a)^=yG&TG$>md{MoWT9)a)ot2;!dTnGeHTism`I5^Q7J&Au?@ zNRc{-lLTQ->2{*Xa~x25h71&`ZmTR0hU!liWfkS39-r%u$HpfXQkB(oaMhA6fVN)e zTJ6(Fb8l6OHQS91ZOfI*3j>9{{!M1Cj@F&@If2~EVuCMZ@v=}1%Hw5A^yTWZuhi7r zTbHP5XZ<7IEY6|5IeYgAuK}{h-P$<9QH6Dl%8Wx?R0bctd&#doOaK%OtLa=za-%G1 zwbxwhiLAKA<;jVM?~|SGGHbW^3oX*_qhMQKB*iuyhQr2T6#6ySHR_Dn@pcp><}Z~T z*UM)t#yK~v6LhbrWmTFbrLGZPXvUbK`_6ivp}Rix{-}?Exz_an`P{j#Bkk2&J_w6L zby$oQK8q)&SwtJ!sTPndW6;M*gDT1o zwH;KbbEj5$jj)Fy2|#P2ZjiTPy+o(OLiC+!gKZ}$io4GsW?O;X9Uz;!+8^Y@4)4Ba zb~X?9zJ1pmrt}xR_vT66 zO}cJKgIiQa$~+&FilKUB(ks;Bly|b)FM7?zn{44z4CZLpir$tetH+f9NmdlaYTeh| zrd&LEqpz!U2CQ#+d~w)YUS1_MnsMPErr!zhkX~ZvXa$)wBGqmY6}mfx4fUr%h?0f5 z{GOkwN9G8DOSlIKLSPSr8O2Rc2vVl}%6hHh zkJ@4z&k8;YYCSJTcBp$3U3V{!4qlX~asX{9>rfD%>F6x7JJe z5O71*;i*)+i9*R<(ypa+?;}yDD(gro`rMLp%{bb^#wSbsD8)55jZSL@TJT1oP7$@C zRlAhI@_^dK3T(z!oGX_Oo!KH(q`eLq+V?PHyzdFpQAwnMt5F@BKB1e9TDf_1W-dR4 z<@j>c8X8#PhIs0Q4GiT9md22psC;uCUHb`nSsF2j&j60SKh29jX4vLOc{sZv*E4=f zcS5?Z`NFsy0_KZ(+4qGG8!R`9P%W>4JQc;T&ekt;r zoSZbnY6ruXH_kFDr|Z*w>uKqE6?_b9X%v>oNno*{IqfDXb5g=>3(hTx23?g;BX-6LD4`UVxO>ZVO4?<**J+NH>C2KSCPg<5l(h_=wcn zvh^G6Hs;)D$=w`8j`?YT0&Fy3Hih771ZV)T$hqV)>@81D>0PMes5x0!G4kBuwphv^ zgIEN|>CynV*noYlF^Ca6kWGl86lkcZ6oS>bwKJ;GPBwUikz;)?NADo2qIEE6r$HmP zwC2W~hs|t$Y4l*Af=0{4;S@XCKoKTW7kyBLY1f;3>dkp8d@S7fDeNS!*qiPEy7^d2 zb~y6Eo=2@{T#mNjj7fGTOHJ z{$7{_t?O5p1_gW#6ei~SHf@<7C3%8iFqL=Js{eXNS2X4$uEpK2*aBCVq*ouSV=G4< zw!vFEOA980vG9>Y?qm&Gu}jrZpkb2escy1WqhSuY8k zBpZ4b&n*@<7FxS93AwCwymq>(8iF0KAwAr-q2eFQOAXw?lk9PzuA1MY2%REmE$KO1 z2a8`Pg2C2ykE3ZmaoPD(B`#)(^gVc3PEoq!y>bOS{PCEDy@vRZIZKTDRlZH434t);s%v6}=Cz z3{P%*cjL^qn}+lX*8$RYAqSOi%vFfpddP^jw_1F($#jT{xM=u=PTU$9AIl$X!bimh zI8L~n`B5=-&RIjx=!=J(bK&(HlI;p&U71`3WTf2G`Zx%aH{wp$^o>(iKPtET<%vZ; zk1L7I_~CU7*XNN{***kPkf4h`Oml3+v7qL{3-xvHcZb!m8(Hdb1#uBsgS@1twZ+i! zle*%;f|e5vScmht)0e!of@TuUL1w%lSZB-|f z%$r_~&ZVw$GfsQ7X#lC6wu}BHo#Ku^Ij0^zdQeK|s+vZWWu!li7=J8kosFcejEn7P z5$9QBhPy=Uw|n3+!NkJJhQ{fSnP4iV+&o1!!~!u;4Z+6_ASZ8Z?OleT2(XM~%xcLW zcPKgNZTEK3Sm<`!l!K;Y<`?ACheAd22Go3~gV~U5v5FB*${aKYIP}2hv=!TIe>5_K%HyJ9IElZ}(Q^O%$ghZp_>tb!q z7j9CKd!D2#!FEbi$kK#wRgVe>NL1L7QkwfnM#(n9sC{W93BAUtcv`fy+H(GOm|czd z{$E*j{(|ua8f5MqeP5ucSpcG3<_|2XHB%8ff7u2vh*&`W{Z4x2o zTg9!a;59$Xf+TXR1-W2t=o6eJ-I$`e>8h@%^LvJfc>xp}m$x{@u%mdWE|ssLke0I0 zKHW#KV%DgFwqgoXTYa#YT%#HmDyP>M$ORsRF}m}g*4)m2D;P*g)24QQqXD}EYhF8O z=$IAr8qq1l78-(EAT&E?#mk|~=Z~~G%BEuuO)ym>q(a4@(`z$liWf>_vCA1mW%czo z7cbtpc3!2t56eJD z9g+&>35nm)?77QJ9g4G_7Bvbt(vM)q5QeMxe!FT~%QCWQ@NACrEA)OX-gdWWN+8;l z&FrI5e?!Ms%^82%jZSxhvN|EN$lK*ay^iM5Y)Q#UIb5X*<0$BqAmDCvx|8xWa8}PF zgepy9y-|RS$?BOfvfCg{bf%y;<_ICZtf|2e02+_f=L&HGX%F;rMb?T1OhRL;Q$e-P z!=pw_GnW(g_CQLh*s`0L0@)8f7DB|($Az_g)&ND;IN5?ecrKX)oT=;+HROT&l=I+Y zbw_F~GGbe4sSSf9CUw_@dNo*-*Yj_q=ybw6d~_`ykE&*HVVWUiQ13M@sonONUkFIA z=DCVGF%rMB-sY*%K!xXJ>$YR|sGCqgLEG7qtDp!%ev0KHm-zv!bAzQJC>t zPLigzh*F@{!@@|pIrVOF;XV8}^F8{uldc9$n_?D%d_O48nJ+H9M^2C{tk68oe-=k+ zpi(PmXmq$rZ6htO#a5L@;~`ocE|wJ*M)>fbNMV&0RF3m$)9(fs;^ca;e*X5JxtKTZ zOx}7S?HlN>C&74O0x`nN@!qjpE6dg4kr&?n#5Sh`+R4rq`N1HDB_kAz@j`)2k*t$1YU&{OvH~%iIcL6EChl?oe z;y#jw^ysXvv)Xw2E)`Fz$RhZBu^Z<|d8$pZpTX@g3seXpbzE2r3;iD*#^xkW$SsCZc+SrPu-sDSciaTb+Opql$0mQQnu{%5 zwk~hs^Z|Zp1w+3jKBl+$Realu*VdeCdcFGS^ytj!$B$lMdupW64OOIWNcmh`H1CN7xTzN@HS+iv{^2%yL$mxLg6@O&eJ`XdV3tMtW7`+PHGK?AfT}=o}QR=n0-+WR~NCePHHB%z`E!ih93BY ztS*ko2|1({Lb{_YP~n^;juG489sD&4xm*8rR$9 zlx67LGOL{pc5jYpy9n_cbI6~XEoXWin+oe~YCUx5lb^G~Q=SY*)-koYcnQrVj;_a) zg1&K1O#|y*!K~lu>7a9K23W;_C6lSu3{^j8p19sQ7dpzgBG)jXMb&VaRWsE1(bUBt zpJ_6uBUlZ zrUJ5Balj#2!R;`msByD#0lV;q%Wb`OTHQoMSw=PJYN4~8DOCqYVbAG8N=4BKB`rmJ z$E0Zr_J0EdlLS*$&fUuVuFnvtCUEQu4&Ikjj#C?;P|g zQqWr1#`O$iR^sNUN0B;2t?I}Y%+Zf7_~|4d=)g=rs&zv^$Wp5(g9GkMOQf4QEvl5n zP*G7Aep)5ikQY!?LRkb|j<8r~&y$yKljv|SM26l<;khe;5kQ0JYjLwgK4Hn;MK}#! z+A*r4*dhtIyKpbv1hJS}+`Q50uBC{e1sqO-=C=)qlTNUD#X>s7rOjscnA#iZ6mg^@sPDgUTGB6l<@^jg?<{%S?$0KHPa%51l8n~~B@B?`Eak<^BRJWf zEeH6<8APO!C`U6jQS11(Ysd%&`=Z{s<$Oq4ocZlqC+Nfp?j{(QQ+DH!Tl@1cG5;`| zx#-S$-gg;t2@mPUG+M2`U~sNq86A*04GOGcprZ0hkCmcBt1CS~8d8^H%Gu!G+)tI?HDo&H-2oie3NxHeXvt%fCZT<>S(vr~Cns zJaq{JV?$4J4mU~<)MBBa_T6>X?joH*z$6@;ktHOLF>FGiq8EKG3YKdzWtm~4ZfSi@%n*_N=3C=P zQg!R__F)|!GhhH2dPSgCRMBEpI4V=Vr&f7@x^2J72w$P&QS?~VHa=+Zn#PlBSLSl) z*ed2ZC8$UM#L#xqj1gHWIz{>+yy(ebY4D=-#>bWDqmlAs_nse3eEbH*r8n-$6=#EG z@S@}@N!47l8d696P5^Sk54~L3rA6Z#Qzflu>~5XZ2h>%-YaxYpb7*($+lJ|QO>j&J zw00!DfVKcM4LIw1mkOEAH<&DAErpZDfslT<;vYxuF9g`U@Vc3q7&6MIHfsVkB5USflwvl$21&QC5 zaio*F^Oe~fK^mkkR}}hEgp#9lZK+a&$zihO1eKXZ7HE97*xWp=kigWb-Wf;6^Lf=E zmu$!2W)I<;?bqzE;`_Nc*KG3p7O&$SmK0 zr<*R7^7N@DPkMZOmff+g$5!ndZ1m%CIqYW=@zR-0yFn8{)#iAV-wv~#kpZV{E#i<; zU#ggEMvpykt(a=ijHrnMY8;lxO^_B#ir6`5A-8Za2{JEGs$5yWJwf3U>_#zcLMpF% zrbxM5qk;g?9Z>)QZA*;a#IF$1<&BzKn6x~;gyeb8OYZ|g5_|K~Bg)4Q5I_D;nqF?p zx3}J^m*g;d8^bT0Vm28dSib1)%~}8vo9V?sg?fzYI3~3@WSr$Q1#<&>d1Df0tTq_0 zc@kDkWmY*fR?uFwTpbXq^n|S6UR!g6@3gbI*Umz?cj^Ce)q9@^cAB@M9t=k_z|d+s zEG!5p#q*Fc1mG^s(Cpr=m6^M>k~Hty#>qk(io-Ocv5eboItC3=Evg99 zB#e*PoS1}`U8aLc&@OSnpTp05ZuN59+$?glN=Re*nUr6bp<%9F^i`U@a*weIyqc_o zofq0>S-Ow4&BA&$X$8vuTtI4}jH35AL+&j#e~Q5%NQ$M63ddN>x2+E$16c$>?X>Dn z9ljsf&2BXdT{7FhJ6=6Yw=-!8YqT~sEB!*&?sAO+ug$T%;*7s9Ud`FgDUE~42dwot z9yxLZ)+}DE>a3M{)q=8XOaFQRDghXk#Z@$5GHA+da;10VeK|Sj8)3`NiKr8+En!0(y%YAR}j?)w+MoE>N(K!yH=IzAI*x z(F{0Xtmu_Xfu-zVu%PTlmU?MctK{IKwbQU>jmYXki!Z69)sI70C+Z#R3nCeG_jVf8 z(!dEN)VoAXQ3b*MW18#V52iH@Uuuos2N|n*+7%&}S|h**gP5Pqz0AucvsW23CyJ2! zkV@vmUYCdExHmNs?Is#_mzWx9_kpqe8m8H`R5-d@Gk1)4#o9=56)SYA6$Ms4!?wBG z7HhD6Sx=cjRb8-}-QuYwtS^{Kp%exx6DrNDTe@3a(D}O%iq%p(F4YG4YVvU|cCVxk z0~BQz!&)`VwQg%~&|HZ%IBxoC1|&>zia!b?C(qsPKrn6aqGsVZjpS)10J?lpimJsp z31mhJKq|8hKhp3hm{o=|-4n1kiX3u51|PJ8IkwmoRy0R-G769^Q&`F_E-Gp+eM|J> zj$#y~atbm&$>3<9@`RGq5WlLZ9!OPJE^4}$qAWUR$E6*uf}~jv&NUPcV;L@vO?Jw_5lqbB78D*h|Zn zdmJaek}3Usoo0T5c>4~q7uYI}n(iUkf?dhd%sUKGjYyBqEMv>nl5sDS+dgM1#L*4} z&GP|5Fr~e!PmfT`Fzp#G-u6N&ZAnOoS)zid<({+V+hMAGk8w#|oP_IP)Tq|yW!hVP zU(n1N)roo83DVSG4;t0UdD#x5%|>-bV?NOSI>&`psVIHN52u_2t7ZH?aW^fYH7Hx=Vx|ddBKi}t|AVj^;!^Z z1?{-&0y(w3V9|mIx1>WE!c=#srkBrHK-zw?9@OFlDU@o>Fln~krYwEJ?8rh2I_kB2^ znR)N-_uT(I=iGD7bs?}$XjV@vt%&s8JRpgjrG*bQDb(0^^FTz_NXuL_3t+y6Mbc4n zt-@SMDZanY)0Coa&*u!K7s|{#MZ-vELn%F%vn+L-yKassy>SJFMuu+gm$S{xwEQHf zB*>bs0apbtEQRPDN$L_C1V8{`;_iJs$O*+XcFIdZZCsx-(Tfz1f272MxP@m?=(2W; zwjX>^J^Ir)9O~#f?wz6%dZ=T6sH0PvzsSu417fTLDBho;Z|LSeIXOWYIy*w$N)3Hc z725m@C7}5Jt`_F!tcq-VSvVNj)#z@vj4b4_qXTIOHz|2}FY+@Wsxd|icPNlF6!C%y zt;|}AijeFXaMgU*f`-xIh8t{HL3?oWE(b3#wl^uQhHW)EeDgpbtZA5X?^Zf&+3FrG zH`4${!T}p6R)c5zq|ZFNvgdt}F^XrKS4##RoK#@(LGbaD+zhCTn{?2#DDL+Py@r6p zEnss5w9lxVS$1)oG_H@J?FZ&ZJ<$Ri8Q?9D8w;`tW25cqH-D(zLe;Un{ff;Nv`m?Y znSyz|YsjJ;7Eg}tz_9)v6*=|>+cRV5q6G|M=3{^Op`v1QMCU?LNbtitschi&uEH<- z=EBXk)_ilz?wj{qdRgn<%dfa{U-+u44?gRfYj3*w=38#P?asUIzK8p2GsdZuaEqc*xbB&xaXX|;mwB8%FqfFPy zpD+ag2m6>aT*~E^2CYKDNQ2-mYGXL>ZH#BkV-Dz5;!A}zeJu1Np5_A~p-k@8-s2;W z+2lxkMzBIob^#JDOlPT(&e~SNyrb;uCq_cvzVczB2<96*c!(_* z+u=+RkGmze=ka(c(YKWlL{1|gO4?@cQ6=p$Q@sad*+biavml!XB*xx=5-%X%)mk^Z z>5li3QW_g!2qeqdvX(s^8ibTAxJ8Z55U8bj*kN#ON|ju3r2-6j8)s2{gDg7gZFRsz z0*o>eI9RY)@0i}POCF4^kaNl4Cup8dVsSwJ9KAoxHmJ$5 z(A8F&b;y^pKyM)8e;@Db_1YZ3=u%*Wv7NBgp;gD#HfY3CtDsFM29XUO9G%vnF&b+t zY5Dr>|v{%b`7!J-(-A#7%RCx#lg^|UbyC=SX{EQ^=U8iO7H zyESle0wZbH0q;3oLm>#AG?^C+h9evUbptp>O4S}`)6k-Vs?h`&$+lt2ao{a*aI3I* z&*Dk2_h=dbx0uTWEFOkh0KFHP*Ra35hH=BqS{Yde3rE4qz+NyniI!3!W6YWbBZC8j z96#IGP+bn4p(DngmPMlUybU^R@g(pIG^|uFcfuZ`8>=UGx!WmqrS>F(!--+bh8bd4 z3m_ONL+g#GLvLWiL097Pv=post!2q@P>Erc+)&!iaf8C$SRzg)yQA6@qi2tN1FkiQ zuPv90>Db!>_fZ@~eoCagoZH{1WwU7vDxAIwE*@`L%wvj!Okqsxp_#b8_!deyIOmi+ zxy$`t>WYbxJ;6H#4o;A)*_jD`XHk7PS3{kSxr;qQg2L6%-9;XiC>F%*fK%)D1w zoP%;99}C3ErXWsR&E2lGy`pxA9SY;?Z9LfIwn6+h`X-22d9QXaf61jnGkE!R#&JVM z-OVb|JyvnmrGgu`Xm?+(=}ripIIyR?JzFvu6wd;HQ1XE=hkNh5N!v4vba>0%;wIi8 z7N0?~y8idJs2zoY5&N8%>~2y?h*}SDy53tA!D%g*!|03RTgopb#}y&hDX1b!cJAO_ zm4>13NWgFirW6<4S}SAt+ZwR;uqI#g)?oUmPzV3YrjSknIux>d&Xq|~@and zY5r&_hjkkZVFvr$zJWgmV?aP5aX78gZNE4OzLz3?F$fxT=&jm@hq?Zqd4D1@{y}5Mks@3{Is| zEACuD^u_1Rqxjj{w422g*P?|5)3yq5f2Eer8M@u3%{UOxg$1#X78aOQUIJV;TG|-X zN<)&%w?ctIr!r$r=c9#%WmHGB0J=#zGd8vOV7dKI1Nk`=N_joNvOoj9!h&4Elrw1Y zwYmjwH!vM;Fa-fy3<+43}x^ZblZf`9FAl##NcBf zYKqykAt)he$RzPd^K|`E;*$O6*V)J?Y}Pp?^oZYFd%mED6InCMtP|n>uejlgkpiDD5S0}-9oZ3H2!yM^Kyl@{`Gsfv zzEceN1_N?%4<8vcFG9ioAbu@@nhtcCbdM^p4np2ktcjY5^6Dg#mlp$Sn~KGV2A@(} zAgUeCI&yNnr>k!aFGma(ZOv{ZJ$eHix6oB74|>K&w}r16y2xYnN=lmdD(z;*$a^0n z!QtTmyG6Dox?tE#+K|3PWm0X}vc2`6I?JAmD>z zcp*hbX<%fg1oH_g=;%tpkM9U5_WOoDV=N4S(i7j|!4P)@W)8p^V_~pl^Lx86g*wQd zRPcf(;rA4=*Ze0icB?cDyozox<+(6GF}r((hBW5knQzjB{)8f_MaSGx+^a(gXr%h|jw z82QW?vWe}qMqJ{x=+A6rQVXbAsaI5S{DJ;m>8eTfks#%1WaNL23JgpQ}h`!O* zdh)~Wh}~vY6)oGvqUdjL4u458Yy*rCPBwg-HRq7&vh{oj>@5!-=8^OVf~jFDM=Fqv&p%K;kuU9HliJosYLvCWx|dr%}!(!M(FZAIHc)re!K zS+hkVHXur(jN=|`2cT+i)19mh2k@(^t(YygnFVv%%6J;A%W%{1ps$NRMtqS|wqggD ztBO{^MxxrT=*41SneZH&tQSEzsH%-j2nsBZzr!-wk7~>1lj}Iy4EqsSM^HL3?2eOF z3#hhkHy=Dc@Eprt&~5lpZFzA19oTq$AxeZ_SFzQ$kr3h-c7DztC4|%vLarn9U#;@J zo)9w5o((sN3 zLS$i%lf}XuC!6#aMmx9xO5C(uu^XY-o6b;*-L$y47;>B(6wSYvwRQRN+XRK4+oBX& zrx#6Zt6nruxvh;*?0IUjoAjb7+RDB+02Mje(7dtaoXhCwFMyZ`K{|Rp`+ij&A%9Ub z-nA1Zd?O(ZKn^fgwT-|6A{{gl(%c;%jdb<&hL^IvGpR%U*Tp7|4fP)x)%%CXIo4zy(x zwAOZXLP%W=kbO-JdENAD_O$#g5pHgC^@|>R>PrtFzbLdVz4-CxzVzu!-uuD}H#EQG zWpBLokAL&xkAD9xH^2V6>;HM@J(q1A`14>s~%|GC${v#WRSJ0Hkg-n;+GzrLv>YkuUPUi_IS$0ojg)(dC*o&* zG~V|Ta@h-SeEV|1*T3pLz4K50_SqjT%{=tK_B{5}a8$ol3j$ApAnpkYV^2(vY_zimSCDyh8bq3QM_4shF(`>%eHx$WCK+sDt}Q2({_{$c+7XMgcI zpa1o*pMFW>z#ZQ`^REZq_~V!V=GHGyzw3p6eD#6O6R+BweO}vN{`^DvR}a=b_1(X| zfAO&-tY z{?{W@i^k3UH$1)Y>Q4+T+!_kieeOT5`rd25zV}0yePZcpYxm6Jmki$DL)4OiUN(memI?|-EBjgKY2bM3#}`Ll_K9_c^u--oXH;N_YBe)Ln}`+qRs)0wXQ${){v=tgH3Oa z{cQ9(b)TI2(i44u^423Ssr%jWNBe*D-lu;0>A$Br zVKVjTH(vDlJ)%02an!kSTm2Y_0YuYw`uk+dW>kqa+{oR+3G`#MI zf3<1gwf8)A<=&$g{xX*R_t~>|z5jRH(!cwg!S_#WI5&Cdg74SX@6JrSm)DH`@jsl~ z_1H`P=F%S?x&5r#Cm+PZybA9_zgYpdc)uS z%Y}m*PCo6N*jo3%W1qe9-(UTK-~8P|#C%WJlb@KndgEIj|H{99^xuB>rn!liee|-q zH-G7;zq{?vKYP(*S7ko-jz3H9e*6W+<1cof_rvep_2Uo!=eO?qlkZP1_NA}*(+`d9 z&wlE%1An`{ZnEo*55M({{2Qjedu{yU&cD59cJwDtmS(m-@w$iK`i29qe(s0g{L`Di z@`3&zEWZ1$TizCrS$mCl-}dVNy4rl~-Azju{Bm^LSO53te(>WjZvXzkrQf*s#20V9 z>b4D!Ej;=6KR)l%pK7?g=i*04_WkUl(!)P;?w`J;bLQUqi$=b)>4g5i$Ge|O#t!_h zrT?R!y!Y9+{mIPT|NfaPyEeV$j_;=vxBk|-{X0!pL-?zW|^Y^{?wbviG{a3GiY2?6DZ~61Dee>hHe%rb6dtcrD)a<_;xbcp~ znzvoOt*!T!AGs_0rAzPl-QYire)FEi-&!BK{4Z~Ks^k1`|HT6@Dn0)}?e!N;JU%pi z?O^*q7B9Vc=%@QX@yf@(^QK2%y!+pKr*?j)_Eo?7*q?s*x7diM`y=PSqj&Bt7k{(+ z>o4B>i*MX&d}{9SFWkjRytM2^JPoMr|^K}0=es<5^|M=B=i!cApJukiU=aC1_ zOg;P=ec*Lleigm;GG zd|)-a)fBO%^AcQ>Utgd(Vf8^uOx+LCN zcV+Y8@8tjUg`a!#haQ^vwW^c{Vm>GAd-KK}T> ze(xPuz3%C^|Luow+VSZtKlACaD{KDbiJuf68|j=r@$9+gqfh_^{l;OjjH#xK7ATQ|Pq)=&TC?DK!|ZTD4szm?AdxAmN*Cq8rUCtv)H zqbHC3=LOR*`e^piUw`JWy8hvF$KIa3^K&;GzvpGo{`TAc=B|&uz})wmEwA3Tujk%t zr*8lF&6m|Y+TQt!S3UjsOUFxh-u>FxbKjUg_ktf>`oj-?j@)wK#`pjARh!87H@^SN zTKJw9d_jBd-mSYo`1n(!&p+=-`mS%Bzi;O+KKfw#J>QPKX(9Ia_dX15$h`M!bCEkb z+}Hfs$KFwY^XIe=9&FfSedbGFYk1>Rw=90t zK;hWI+_^|Q|{_@Wt<6WR0gvo(ntpOHuad8plFuv%wr7k5&_F;h&mg3>hb4#49x~olOMo_O2)VBo+E!af zNbOc~0>vyCGRT8`|5#)K2@VKYDHkq6NEtS71yloX({A2^vraAt?q&&~`+L}TAS3=9 zhN7E2haowieTSjp>A#NYX_ITnSvY7^7Q{tU!vwuOB1zPjq!yCYyR&X_w@9=3d>DIK zOdS?u+UahVq?UYq7a^b6MHwHS6d0f#+hE{MG;Y8wj#)gPjCb(_@M0s@S1h_po2~#6 zh@7Z_RS#)4VH(?YiZC1nx5&xy2pa+TJVM61wh;0VlE-~WJRtDYFv6*6B%}tY^9(|2 zP-5IhNW<_pLUs_+xM3$y)|v3ISP1x;Vb2ZrdzSvbehzw(g+E*9lUHt~pHJ?FhtN}$-+|Pif~NaxNOJ>T^gb~& zcqJjtFfN@Ne^$EX;^gzrh2Q7EpR?f)G|sm2RsmF-Fha0=J6Vt6vy+T>)#I#eB`08< zxNd@~AZlo1PlC9g!KDK;tQU))h2bQG%Kvf@PWdc?F zjD3gg>n@fC5aE~X`z}Jr{p>qzbN|B9!)n!7zs@Fv{3m;U4k6?c)&>AGhkZYf5K?62 z02bWF+J6Cz6?=XmA!Lb>?nQ)<3}dn+O21p5w@{6+Tta+pg7Vpo7Ji?#DgLdYGg z@B0WLDfT@?2szC1wh=R)_VP0681B8$ZSl&J;lhxZ#2zd*89tJdEo8MK0kRetMut!g@at;zgKEU{% zXAwfetek6L>{vP15<))9z61Z?!oCj>LQb-B1_>cwW6y^OA?L8~0Oh}9WeyWUT=sp0 z5Q1_hAq4iCkFxYJSdHvE=pdh9-w(mMV0p&~A#Z1W0e$2LS(*t#$U9)s5JD!EahL-A zB%{OY2_X>%m%qNEmgKj>Im3yE2&}4ya0`Eg043f>fMy@rK+dE4Ni!_{=B+mgO?qtV zmUi}PI~*Z}^kOljXTU-PQl6=#>s zySD&7Zzs=T?-Ovu5^isoIm3M&oxS@4ANTObaB6B4GU2`s{$$p+3NAeA?&#>iUJS;k zhm(ovnRp^Pl$@N7jl?G6sGnq+n^_C$!ITbiY#53T%#5f>u3|~f&@*|naIJA%&lht> zTiVJ)`kh19MJ7fjlaZnE*hDfq9*K>qnY&o#4VW1+oaMOimB2CeKVfIz15? zkE(h4SUqR5AuAh+EyL536N%`=P;zG4)56PG&W57pxO27vI>zRWQzN63@q}8#ex43Y zLsPngqqTWzGM*Tjj>eNi1CV$J8`gciu!Ahu=5!XqisX&Xu5PH{43SYCfwJreSoTIr zm?ax)-6}G}Pz2V?$K&ik66%E}G)>J6jKv21;}NRR;-+|Xa5|bu9*Q1ShoyrLORO+! z7EE^uirzjjIdn7`kKGtej>X1fIF1c`N*MQBp=muh{FG9m9+6FuA?uN(emb7CGx6y3 z;pjB)lgPXik1)<4luGC!$3{?mgO2|a_I8rKZTP@udKf?x zEE=gDggjD5rZ5?m#cHA5FbExU*)$x=wmXJi$Xj;KSnBL)SDO;zqn6WM!*SJ#oDM3n zbLA5Gv?@i4VSmV1=Itrn$!eiA7)ce~5ZDY-7ecUE;ZIn|eJ!-4@qs&*3w8E}@R#X? zx*;_^fesl3*Ip`GX2ET9vLe0K(gfpimN=#sQxNX#MXKT@Hxp6=;sk6#aJmJo32?(8 zJCr_Tk-XK4}9oc;PuaOXKaAQ+ica1r`S+!_enNr#{7fg4lsWoHF z>Tu6Q+BPyq!8P@q(;C)V5fj7sx3wu_IB7eqwMK9YD%r*uSgkpluDQ0pVC1wE7!HAH zYcXrNmUg>UvZ<|BO4EzQoSDYRMy*X?Zxq(lS#Pq6u4xs*T2oPRNN z99lkzc9h28Ur1{Ob|>7|5!Q<)O<@~o8yePHONE@_I3dTiibW$s-!53WQl3#MD?z1Y zirHZW+aa5nlV#}Hw{f+GHNLO0>7YAPB?|AM&C|5jvi(RIay}w`j54YpOVNdu2D1kV zFT7}^Rvu1{g=}2FNLMdp!rEP|%j*Z)SfS#!AaQ10mI$ARz-?pYanx2MOEJ=w7>HIl zOa;Nad5gM(z-D%CCD6VQ*cfFiL3RN29@m`aRstL47Ij&jzhO;mY2^ zk`~6P*2BFqP;33vNDKv!M%t20W+@=ej6aR!C2I)iGX*cXiJ2D(E^s3?Hv+b=hH%C% z${4$AF9~4mYRIsUWkSYoPtKu?UCu0&j>8^p*zKax3g;zzQWaxUTNPt-UhP^iHZ2h? z1w)L^FeyD{8cwq|YUGNJme#?v5Nzmy*GbQ7PR=lj`?OiZfa7szpO!K8qG4-v7jpK| zsI{eheu;){a4opr$S!Dl3ZmE|lVlqiGwni6ORdz&%RwW4NU&FTw0tR@y1-j(>2auiT5yz%#D1jCd zu*Y`vg!?)=s@xU=;fzu=?5topx(r-h#^GxD(W(eu5B?7)7XU}O+V*c;V`NOvQ&E2% zkg=Xz$&hga3b6ow^F`2#h!W0Z2E=sDwA<;N zRgmRvq`$qJ#9J>z-2i^VIfh62uOTBro5W?3ZJE<;!_CeamOW=6w+R!cY!hPas@f&$ zs@f&)Rd)%;wQPOPs3`d^8Y#^IZ%HZl9x+lOP^)E7>?{>E$I6vJY^APOPN@ihhPwy# z{Q{K7P(-{oF0VRV2IeGN4Uz{ASs9koC9n*XhqP8f|FCop;*#R1uD+$K<6yulQc`=@ z#zDGjl=pNw9E9aTpYm;@I$EH4$~KDrzW%;2{;5iS2;3-Ov4#De_w61`z6fcpxTeBo z-E;HBue~i>zND+3hS_C5IB2$1kb%6sV7&cVAq5m4A>Zfh)wttDIJUi1TfaOJNAM@^1AeaxUhAuZ*9U79CcI#{z_OZ!IiWTjgz4A1sK&5pEgJT0 zDYs8E;Owesn~o7e7tnp0RWu4b&Kae4kR~X|>Lu5L0O@IMG?AE!Ym2t&x<)}W3)+a) z#$gq^RuNP2EfrCKMfO1`9U`iLDaR`MwyOdx^>u)TNI(+8!T$Z-;r;uW4lF<`ge4;7 zg(YEnfG3k#LYfN$F_ygvhB3_K12ZAHH_6!n{5gl?59X2s18@T-2w?DVqB*?|^C#)@ zq0@n$@>A2ao-zS1P@?a?)oLS0{ z;IbgujE;>FS~OA$1GZUtTop)cs0t*0q=JO1K&r@yDSD&Mu5QVV=@=RYRzCALq++{m zEyBeUa6yv}qB$~QJjM|GHU?mDwGyO4|K;PRgVERqkwy%m-R5A@s*FTyMNmSy4A09p^74 zyH!IxTu)Ow+_{3pDG;quJffJ!S)1pdUv}Wk&Xa2h*lCmj+S!t|LH{1toNrHOZQiJ= zfNLWF*MF^acKWCaTypRfSVdu77-aGCZaO4`sNEf&)=~-(|FH}S>K5(cmbgWr- zQMU~rN~N`*KsfXX2dm)uqiM>dzTN}< zUIr@wngnHqCEZCJ;)7=vkn_2Sqfp=&0OFiY5ywA|0(sh2H;qw9O;s^4H>x-Q2a%-$vuhB7&baQ{=5ZcJeAY@+UZZH6 zdEGX1OAyS*F~LM_p9WF;b%=Xb$Y_p{hFCm;q2UY&cA?_(#kXx{q20e^fhO1z<*RMk z;i|Cc`a1ged!(9GpL=s|VI|^_%XF(}U|}Odn<_8}5#9AlC!=dM=&(X5(L8!OYcxOv z0l=SKClREEdvG*wJvuovog5raCMFL>C!qQ*iJ6Is=oozf-Q7%^meXxRF+(F@IsFJ) z5Is^uZuKp{^W9RRVC1w=s9=RaC}&nub_u7889#xgmn>ZQn(^0L)e3E>YK3Oi6{_si z+=ahIYVk8aK>?1lX(17{my)i!Y3D%w|U5$eUb zeRPf2Vqo(!NtnTanuJ?HtIwd?%~MAr$;i|cw`Nw~OP0S%Ee9Af3ua+6YOZ{CtsBtH z)vM_EFOBLu;Zx{4C1bD(MTZx zBNH=fqKjo_w=UIIG74x&8$MEWI~VE0pGU}F28N+Xv6=Y;_ZWz6GJnx zL^3ioG#!mo4;b1mVb4$x;VU8WB_i?I*yNGq;AnL4P;z*3Iyo~n6iGxqnYmMl$b7Ch z^Kf)1Ivq*GCXp57RrYdK53llkZ?5U+NGzTx&&OR=&?amf&m+w&c=_CGWRq>B=bcOn zdLCnnF?F5P z&`yl#c;p6X?%>SybaWz-oQ_^U6OAW4BihIEHgt8+f1bue0W24~m#DSw<)hl$*?RzT zZQ%`_nw+MtJiaO4v1FC(Hj1EauroleT|5_aCEqP@9=Z*HuUlI{1o zHL&+>w&R!DX*1Z47Nl%zg# z743%CX4$A9`I^%?Sqa?R7mW2fT&cyQ4?IEP8|N0VQ%K^{isDYzkhY*j?(qcM4LbEP zt1uTSWa38JHe7mL*^Fak5?0)tDir3zNq$Q!6(ieuzvLs@z(V-<2{fn8I>x?dLw%Kue0VD<0l;I`)a1pNN>f+?O1e8b`c~n{6KIIXsRXGoEXY&>Q`zb9 zZjMXKj4=RJfU#Wr;OeH^L%LsCYrRr&sfgCh>mYa3qD?Mf69fYXaXkh9&zpHYm$T9# zdiv1jSZx!NQ&EJNv7zMDbaZSoLVZxu*j(FP;?~&o1bN5Q(ZuNF#LUFN%J~(p8>j`Yl2YdBDqD17PsqZg~ODMs|t&@RE0&~R~0_35WhK; z*9$s$)EC^=CMt(hwJ&&~r)TGc$`|!4(wprjIxx2|W=PZMZ}C%4r=76)rD^tJJ`>ii zU{AnX5<^VO{PYZyPB2$2HC0qZ1*Mi~>6XBWC6~95GhPDKmYK#wD@)Vqjb2n-q4s*V z;gs@l1(8-N!W{xmJGaG=COAuI<;S#A5?*0#*ly*6FJinT_|(lq}%l1J+0%wGUyS3>Ci zuI@1Y5$dB>@KjCWWwFVkVVhP4TH4v;&>{k~Nla;k9}<_h`=}g1qd5SYz0(80d}a`l z2@TS1&oq$%s7nyIt6@#GNf|4hx7O>lU=smLWEiU^IComKaTrL0!^OJ2@Jirh7|d zYD!^WdE>e2;$om8Z@3xe1&*<4pv9Y@1Rg1c^}Wd2Fvi_jkLAMcV1oy66)x}jwVhoD zPzTo;?%Chn#Zz7bw<6{BgY@=isBDW6M13`KMb_Ei%m?Swvc%r*1O1Sy2hJ{QUznD-&v*&EVxMYDhh?6sNHwLuw`V`DaH{8QPzd3Qh$S621;vT8ab2im%n ziZ|fHs&@UYRqgukQ#DJcDuKY|tu}ZO&6~_zHC+O(0mEfzaLO`k*?BEhGIR9Y+BNjN z@F8L&RZ$LM?*mNTGpXey4xd9iT|{h4lrQ<=3G5){3yg1VGChm@pcYrYyOmQ-#hr<* zh06ZwO&YIkxz0*Bf{v^RVWM9Qgdo%MkR@`cNCMe-U)KVvL?r@ppoU;*qG`*=p3MyZ zT>fmTyQ8!Fbj3ebp%nZ$fI$ms+belv_?I~CQvm;h2@&0x$CprgmC2U7I0M7l1?#4Q zEZKW%3m3Q#4q}h3t+va^>5jWzCt0eGRSoV0VmG=-G4`TuN;`&br?cLj3>{u!zo`|$ z2flR{mH6P(Bk_S>76i`x*>0KuK1G5CFiO+#A_^#MENE*`yib{#y0>ZJzP8Q-Z5VuM ztEbJ+3M%aqxzX^_=FOB|(3N5~(kE4IH`}V(ZoaN6yy%Ell;Z+aU5aNFL@aPz+f0?f z0GSqrn~z@5b4#w7b~FQQI1Odnaf*hK*{3;a9ZVO&WHAy`BRh#L$uoQvHzt;H#MC^3It_}@1EX{&M^KFvJjq$_jh%4gz*ojql!pE-L0f4qo;PHZpg|= zp%QNKrh6zxV$w!B9l$&a4ZIwz3Se~GGd;NgTi%87!L_xJG;*LTfnKkJI;@89lW|Yf zOQ?NEbSyd!r@u#{1M*~+woc*O{ima^V-8vHDS%1ZDZ$Bg8M}I^M3Ds}?OL{(Z)X+x z{IPibRe{O&s=&lh!6f)pG{CBsUPfAS^pu%1-6d&d#D5ktpv%!SP-IbeP5OfCby)9~ z0R>c;wVCChfG?I~;{5Xl%#SKI(nVd)@+>p-6@a9#qyIn{{|F$dXcjG4jb+Z)*r>Fb zxVoj&<#lT}0myZ*dVaRX3->s)z<pEiNny-CfcTqtuIPR zy9VQk2qxu>cB|;N7p#l{H^_nfEJS9(nA8a8geRyVtOmmr&Iz%gwXN_QvN6h6MWj_) zTh;pBQPui>j=H}2SYfzFZVJu4j27W0;1pbLi)PWzyy1e|(VUjm3z-lMVnNH9^9DpY znzI$zQ+BNKf=1$iG6Ez}`Er?c9nxC))E?yBu$UEe`C^tuDqmNWVj%2L6>AyA-vIf7 zas_^Jl1sl#%D||%pf8fm<${J>{r#srKfWb!*V;-Mp!S_xuX8I^%BUrv^brgABD4m9 z+d62AT+42^jiTk4u4T*M4)kCNG*u$!`2jhZjlaNvP3(bJANC5i%ikZo%Lhiim6wq! z4HZphv>D2ma;^z75=>sBcwH4BoKY1ZJgEXg`4LqWL0~-|*t51_&}a=IdT_GOb9xT) zhZ6P`kp)l009c@V4vG-7RxV@Mj_{fg9j}NeB1JiqAYN5uy+sQ7t!x4+Zu))T2^9zw zdTvo)qTx~l;DH^Vz%`qdsFl`<(g>qFs?zeNXRjo%1RcR(gmJ(Y(O1S-RC1r5SlgNO z((fu&0F+V ztkzkl72bunvnrh0Srtz0SC7&a53ULTCD<7tW5g5?g&8KPXUp6VgW7DuRrcf79cC`4 zYr|Hlknu#PW*uDygn$mwwAQD+;6p@(|8l1UUNW3L2OS`XAT)1m=%5;G5uS~dKT}9X z+<{$2TohS2qqOp*RzSb*j?PX{^>zZAM2Ux{tSI+SF2%W~5|Rb!Y=?33t#a$coH>_u7Y+EU@vsfRWX&0ET2yzIG}jV0 z6@XGEXDw=Z9lXm6dLeD>(@a;pz2vxB#xlU6)zEIYQj!g$)mFwo`X0v9kAL*dG6Een zX5?1XKxGswG_94>5U6gty1M9dj$JEEB28ST^hM0#z{M*HVew&6MF6}gfwcs*_&uZ~ zw#ebApr5tYc_Jwu(PsV2+Uk2|Eypo)>x4(D{8tvvI$v^(QeKE`8|iPa#J0Va;z$LF zEikZzV!`0*g*l_(!U}7r9fy(KNWWHv6=zn36^klXa5cvYmvg{f5aFxSStC8K<*Yde zWh@pFMmRGnL1%c>iL5!74N;#KrnOZMgW`kZ+TJ(|1fvaNtf!JqjSN zt5-Sr!l*6rObot4irU%+c%HS*IeoqE8I$2EJU;Jd4Nu2LB8g~nIuV}|mL?R~uz7}L zFRFAw2h(N2gKVP)jqR*30V6y(E8qx?*bI`?eY+@*z^7n3fFI$a)@F7x4WA-`6tzH5 zgmP|YUUcv&lGQ^OA+|rHm}e>AQ>55<#7Ipi1}mjG1FmOcX{b;a7^nX-Zr`8E>GMV^ zr>EzgtfAX{48o2J*1GB#SA}tBRfTacRRy~RGhIH`1<_Ft{Mz(Xhd4$^gbEt>M{t%5HJp6KozF^R|St~CidoY5j40e<{+pvp%_K3b)jy(z_ z`&OTOI%kTio6rh?*#oim@sBviLKReB|AEdh{_zQW^leYi{xJRls#RF3zMh^Qc+u1D zri)=puz{~j8SiV4%m-1z7^4lLbu8SzJ%! znMSY3`0)P~^r|l7|2!QYkh`qQV9s-M=5Ne^vFxU;Qme_Kz;wk#L! zkb()@fN82i-LtDg-502w;1Ql|?PXUQ|R#F%CX-#OJ|` zpvV$DbQKV;yQAZP&q5I~tgEXF#lNnw<1mH)@`|hgMv_X19s*PVha-{UrfG{M*7(Ip z5okm7v4RkJMfLL_N$HZc^;(-V-JFgQ8`i~4=P*+;UcWT3n7i(1 z^stfWzOjGGo|~Rn9O&rpJLvtHPCYs=}2Hm7A*uR{-V0tC&XVbv6f(W0mZ*p@9-elc&5I`08>Qly-kP z(8=j|EmAq^1~jprD_`MoIOR0Z^DZ(xK+25FM+f7$I$6vI4~bI|@Hw;b0g%W-vZ3}nds)taX0F7IYLmV@Ea1h8jUV16T8=A?h)n1VD~iGv^w%DdVxxVOS13`IT~>k@O=e z4klyZL@-M!g@r;H-N~Y4QDuD%p_MsuJ-*AZ=P;Ifi=L%Vxd; zfcA8Ud%96N&44vKU@~%x^f?H%-sdbhZvTEMKd+jL^|vsl(tU%VWl2^c-JhJ;2T7wMz8w&$aBwmz$`m*IFVdb+>}ZNTvaKs|qC z7@S#Wrelet$;i-nY{J8FZlVp;;a+!d#ulEoH z!nnX;YK3qvfimkJ37)J5{t1_wvrBu_rdEZa=T(KF?^k8kyj1{;KDbP%f(eLvONite z6^{tTtp(0P5g&E9{oK$NOsAyh%sc1-htFzFaF%q4E5jpwA7J9j-Ylo@D<=ZQs}hNf zAyGg|ag#Q`7Q7t)DoMPqw=nU1iXpBRgC}}BBs>2gX2Rqq!hhLo&{s0xKXDUi_%f*OVfxYIh6*~7{_N4bt&b*_-vCdVT&j3x=$c+A5MvwF_K z@P*r(k%3Kwho#}CNokoFdhC@GU^7 znnT2L)8Gwmz^9XMv*N9?4|6H3EDhU%J!SBbk{pznLS+@vajLMj0?1X4Y9K6<%8V9- z^*3)2&}ap9a`@Dj3ZRF;(eu}qpNF&7(C_1Lsm#78Smogb=SP`G2z&6w|u$wgj1uJpc0WRgER^AY|a>B(n z;sU8>I=H-NxXQ!Jd&jPo3(RYFZI-wEa#s|80~i`{WLS{^Du8HTXIFO^|A-U&007}S z1^Ow`V!LmufoT(N31vO1fEwpknsdMeAI&apS<~2BWsvzAa z2;aqGhO;yk%Y*&NS2tHgs1fMT8jlQ)#wMc4v1nv^A~rFCjaC{V#E|Ze4%9W5=kPU& z=b&*S&n>Iq$mH~)C=EW&Issv2p`&%3T^LsVk_vf}iP(5_azDxwQ=>*ImkGw{M-P2?NlgE?Q^MGJYEU9i6#?Ar!Y2s6DPmU{agTJ!+`}0 zPH1QV8la@+;S)Uc8!Uh+xj0F9a+QlahlWq6cvw&ypnooQ6QX%*i0!xj#hXA*8dGo#|-nZtDmY=jbD+qphp0 z!$$~_pekA<=ewZi=8Yxx5$+4Y<;IJaO>I}{%c?k=3#*bKOB<9>|LAwQ8g3?r144Z* zz(|@~5rV^n$GH{h233h@Hm0TY^n9tPIaaO&28mpdq?1rljHIvI^kUI>jKZd~k_#Ct z77izZJjh!8dsJ&!&7xrf4rm}0iv5Z*9W()lGB7-3DgZ9~u-yl;!j7co;=4^it}-l# zCO{ef>kG;f06}cWqS?W??p0Iu6}h2f;&id8#FyDsys9J2y9^ zEy|?2148O~xDy)d0?ue;mSV0nXBH%Xvxz5lDObI4ixckyuGdf5H~%8^W&k)=dCSj+^(nR zjrDS(qGqfp0`tpfHb-U>lk8SF=;tQdAa|LV6_r!)xECyil*_7gz4F-YH_3Yd#F<$G zzZ$@cLVv~Fs^BvKg$4q}k0A9LYq%mL@xD|AMi*BFMjpcj8u-O?4+Iar6`6`@@lp{M zDB5VD3(~BRR*2)PjEU8c;)ee*zl}UqLza_xH z$~VG*T{5Ob+v+A*U7hb=V-PZOxux~Hc%0wRh&~OT5dJWZ7hD$|8#_7-22!O|&UCUy zCXV;R&e-Tz-9TGw7F2lg`0*@rZ?MM{wM;#vIQz&e4Ig4G4txfHOQ2Edg@HtkqioW1 zG5(_}T)CvG6Pqs8sC3nOjp3lkI9LiZ9ew8S0_I~n+xXG=^<&}y3tNb70wEJv$E}|BC|S75 zLuTOyVOzjSgZBV(?4p&FIbPA4c%vG{7(kvTng^67vIe;a)Dbwc5-R##=v0CQpgaun zieMv~=yP}m$4Mg7*}hDE8JKpRKZctmMb>RX>c+tmRc)qK;X^OeI>h#sNYK7g8!S32 z7njj;@o!gHFY4(m_2=KirydAp zmxj zXdt|4x%Qz+)96T1F-Q2LfE$W2tCw;WRt&8tP%82QXls~J4Vx$WmSZJ<%fZo`%7c%1 z1+s)uZ%U?0#<76O#(B+ zP9a}(ZM~S;=PWrnYpyWIf!x zHSh_l?L|(nX=s2SUBd8JRYb+Ea&D`tQXuj+4A^ElNod}*b0`*{iX;X{qti(Y(;h>@ zXp+hJrGC;fXN2hztE%`$R`E7Y%@px~g3cL>4NONT#^cHO#Q0QlaB_TnW+Ik2TJ_M3 zv$Cak!Y)zdk!U0_8l4`GOjTXn&3ufmXz$Ukp#MQTFAOL&86O;t4$X`q6JFIoT*phd zjlAU=Nj;OHyz|)PNHR8+JRCvZxvH{8SXp9Dwv9(_NX90nW)e^i$}UwE#Ft}zS5NOa zuIlmV_~i7_8xAEpm(nBG9Zp9F4tE@m9-EqA&4pVmSB+o%TF^?? zZ&ghS@3Y)Hw#B3Icx-ZFwYvw`Gfudbx)q?X=!(ik64OeG^TiBV|x1}E#Sv6 zJD1nZ9GoY@9MaUBf@x}QBe)Inwgn{TBt?^R)5E%yj#RuA8=z7JO~)-(>w5YQ$f~)0 zB2B{?2i6x_R6G%xP9(;t@&xjX30M*sO)Y zzUY|nosg#CBS?wl3{E7l$0VjBQ@Fo13eJSr&Tc~&sgK6TCPyYlU}73L^CC4G^(%)% z27^_hf(VM2eEJEzN{eBpw751%X|ajC(|6ML9Fz?*S|~*I40ta{sA$+Bj3IciQwxQ1 z)}mpD(z;{Nhaot}at?NAp%Cb{^t5Z(A;)k-l;7iuE_e-&Szt@&dzCB|Oo#!KOjGTk zBLC>Nsb^B*PP9<0&7=Y^?z=!{;0%TM;#>Up`Z|1Fd&(@dJ6SE1)>^5Z3~QVg0wYSJ zkg*E6C2h%Yv{1-4j+IOsFI?C5_!e|4tcmkvOK4%jMiLh@z1-5*1hh3?sS6wFU}*X z8@TqHH=D_z)TWeOEG`jz*01Tm7Dg{HD_rg^S5xvuDZbEh0_<6-8kj47>3-sa4@802RN4>oFzMUTWPIv47XF=x=P{LFgbV2|B4JB&=6#-VQ9bh@pp##1c$BXMTkC2Vq<+$~6JB zmBES~e*Iy|CH^39aAAV)LjTXo8(f9D{wq#hkSK*{!j{tK$RZ3Xxmd$ZAmHK`%`x0k z5ze*H+@b%JwMnQ%<~8hGTl;V<77ygt!L_Xh4f$Y1b}X4g(fQ$$VGoR^`)|Bq1XQ98 zoFzg{ENxlQFfvkazN!#CJf!-EY5cUnyW0cf^IRHa;w_t_xR5A~tV(m)QkCZNWfff7 zxc7*#%$+P61uae^qsL*Sw1nZfZQ6vT4d-+xyAQryr!VOE<%p4TEO1G}UjwCF&dHjt zxbshTaCvPdPDy~iQs!s-RJn()Oj1$W<|Gi-TKyzKcU>-2S2ag8OPR#bO>NbrbBVg* z;a>A0yQ($sxh!$GT2hBwP21C&t#4*Gh*Ef)R=Z?gbEV6GSV!3BV2a3a9#g0_}+q=K(&bWLVb zA<@@0uBrVa_8!d%)&U$g5^i>OiLglJ5fzT*P&M3MoC6LGxQC5XBXFn$eXq@=___R+ zaU)~u^x{ecHGfc}+Dz&OW>(P|3K@m8l`#u*2U}+n!+ouAhMi`I(Z<2nLH@v9D&kM5 z_e>G=AvO_93=JeB(<5lWP@75dfJbGm2o9B0n@Mr&gR&guVUm>8o0a(S(59xr$%*0E zNOCBKCN1npSn^Tz=z}243sw$cw3Uy02!?w_(*xg?Ix@JuKy&7g=Wz?(LZ=khv2+aH zNPl~c6$Y0xR;b0G$z_;+mOOFiy$N?7VDyp*+68)eNR_;PJY(4fvoL4a6an&h6{`1# z!WgmRlRbY9pGAADQY9N#Ws%X`C`rhTc9vLk**c$0)ZVQZ)FTyhH`{Z z2eh-)OF3~EcaOZaU>eBK>Go2a7IPu18Xh5KXgb`~lhe~i9=w^sA0uuRblcviP3r*1 z`?Sdg!*&eA-lxqJisCwTD*J z!Sy*|i}U@ULnn%5VXbuq;Nu&Sj65?0k!#dy`GIT@Otpr!mQ{luJu1_bIyuw6Qq4@^ zT-G|ia|bR^+QonknJ;35BpHT+KV~}wWUu0kP2eS{8x+8zwetp^5+2YZ%7l=aOC(ej49kI1X-&!%#Se0Bq&;KgtuXwN+iiqxu=~)1F+}gR z+vf={IA5?9b8yQ9+jw#Ngbk};xnN0&S2-1Px(inv%S{(H*rIJN=;@_U+A26{(<(Vs zw!_?(J*OAgO(!7j(V!wYAr<$vl4D?kfS^S9yrQay77KXAv2%qPtALU{UELjF{Ik4l zmbX|WB0+N!^vc}UgxXf^9!g|l!Z?&Q-}gUd!T>oaNq=FDA;T<~Xbrs%B3&)vkz+Rx zjz%U%qT^BKIlpT>HW8aF_h{RI&EtmZ4d6EkPFf)4Y*(@XYe7c{dLtzr8tg;hQjj4v zppm=)crOb$1fLR(^r8tu58Tgw1xs+bCxN($?ubv2U|#zg$~I`(TyU(M5d!}m!*R5h zaDPWfXAAUa7r$Bo`#}H7K2-%|msJI1CsZI~UgH%72tMLrWx^z!jhb^=u=)ll!Z@ky zc6L@OW4)-mwQHtw?9$*!UcbXCXz^|VLojU>VJL4F%44i!76w4lMwaq=D-AbAn;_1+ zRUs;cuWj}89vLxDQpVcy!SWzqz_eCCyMC}@!9RMDS=%B{*AG{F0-Z<{T(xsGo@7yb zI-$(o#HI0kpKp2@qT&b>g!YfpFXC2gNL9Ylj*4bZ6V3x~p4C33To&Y4BWV1wzpmZIKh6#c3Sm0GJprTe@= zjvPmygG=9NSR2Y|w2FF@@R-Mfh1(2`f*aQEVkG2p^nxlHWuFzNDcV>v}yCD1Y%)~@=I-ZP9 zL-MWmyH;M0|276xyDOj}h{=M7|ud3>Z6kitV=eh(HOC86#RF4B<%M}fwN zlm3aOiOMvDJ-r9|!uV%7*_ZNlzFGx`*CZ#|!{pH>pv)`gSa5dzr##1;Wb4jf(__bi z;ijzh3c%e?z;zS`W0l8_;#w1qR2yZx{l|_X?XAzu;iD*@$Bobu*N==(xr@g#UB}ZM z6PerdLq~^>jUOF2G;_N?+#N-UI`~*pl*RWNrC;U8k|OmQIlYSx+}?ep$8ntEV#b}A z8SY*(?}#71-JDKM%^e#b?!O-CJIHsw34Mps5Jruk$JQt85(+(M4NgwSlatf2k=O*g zR5db&asJo|9x&-Z3f_PVYQPzma1TqUjEx#lhNXgd#ZX*Tv*8aJvwTfl1Hw{q|9a|} zzIA9Ic_b1`B!{8{Gw7AhlJU@gJ1D7Mi%}1=mVfJ&Mr8izEMe@)_So2PnC_a`1Cx2iul%)LTSxkC{ zOnNAK)R$5W6gG1!O{(57MKubXRZ-@b^&JMD#|>hMc|#?u!pfbAN0afmN?^+-Wq}S@ zsT@`Wx3qm^Ix;nS{g}!rv9x?%H}v)Hr#E7qH99#Hj~Dh6|DSg8R5ys>`_z4CfJr9KNOpS5l$YCPRE8ZY!EAfhk>aIay%Uf zSOU+ECeO;cm`_=>i#P>Wbdsn&Xq!bV}df zdn_`ZJ#u6Bz(Ci?tUgp2ADqnf-f-M-v-=|>H%=Z|=!ngaEDiPM()z$KF0y!Za5|a* zuu>KopGMi?ZAilLnW^Zs5BNJge&$;9NLDBj@Bx(2scL)UiDQ{Rl0*UbWtDzjbYMdS=>FXn@aw#mdkz~l#+ zGVM;8cDY5xFFV+ABswrUIe91uaHL?j>GbTLfHEr`B~UH{Z4qFiDka-4nGsA29T#bL zwi|AmlOEN330adFOnD;VRzzx%i&`Q2ZiIm&GB3QtBCuU~OuLCaSTUoMw#}lNkv;GV z#V=#lT7ehc)e|7FGNHJ#wU%HoU+BwscsX})=%5DoZJkoI7A~Tjme+?H$eqS&x&IUz z(+81oRv$WMxyC5WZs67KntBWiLX{u#lm%Rs-r@49^bXn0iuGC*!B`M7{FZ9`em!dW zWo3*U>KO_d=u`<#$>BG%Un>|c+`=Q``%;3htaiY`$myw|qi$|ew2TJgG!3>`>)5%{ z`j~39t|Sq1C8=x=>@uxkwY5IYhG_}=t8nL9m~O2;?!&1s^xs1a2s*?8#%1>UguvFY zhABDT$dZ)F^rY}hdg>}KXGbVh`ng=%7!-Qg&VhC|eI0#WzN>Hp_GT)Xh0BFC-o+4e z&y-2Q$U3r{Q_VRT+&1Y_V0sYjOPNKaH6bi*ouZC3)j!#3)HF@6T!3tTS$y;eZLrostu%No2LE-fZ z%_>ta)AW-xQZnn3RGQVTi_*+v4Yw8Do)#Au+p}(7-nfKjb5ym&gF8GxRZ9WE9qLZO z3-EuGMk&}aUDe+JB3h-4az_-Kys9)eS5&3B`N#%EbJIF&<_zU>%+`vABg&Q{O-JHJ zZZ-smi$=!dKOvnN7PDqL3-1=pjNwps26nTuW28&Aq0N>G=+^F_76{s-Ia%E{3v>I> z>0M7*w(gn>242Fv4?Q39mThobI{{zIsDjwI1~@%DlTLfGW$UX3T4{IS{6~Nqhz%4r zxSaJ8YO_CRf&%?uJkdbuCD!&?^X@FAU`;tPou2AXxx6tGk+8vI}56x+F4aX2G>IJz$S_ih5dZ@7S%%dpo`k z*x1=PP*eGUB^oeV6_;s$hfjxaiYDtSCCFvmz=sgl?@q3Bk{$EfqmQi7_)@_hMC>Y~Z*t7`f6smo7V1B(SXW-YQ6Xj^l(p3lP}D)XQ9N2;`~%PcnROMuG?%el;Q3ml;eE3UJzuLGP&l&x{qE6y|9em6Ov5%n&)=tKv- ztFCMHg9;0b&;H@laR}kMh^^8g#GPFNuvq8yMSXpRam#jOOYj7*9a<#zHvbFHs%)fM zRyDnR`um}zKBb+`Av1MW~e*u&g{)6+e#-Pr~f!0gQI?%?Ki z^SBoPx2mghdg`XSsm~eckbMI+%N`>hYaIkLwp7e!~Dk?A%YNh zT`h6E?Rvsm%{To^m#43!_PAw2i-(Qu@W_yoaJZcMZij>9m=(f7^5pJfhmbB);VC1h zQ*)=8h>mlj59wg3^SEaZ94w8? ze(9Yk55>FmLCE~Q2c@1LHRLJGfP6L`YxGkqtMkjR%wJo3HD}F2w+A_f&FD6KV?i(N z%qL$^p82GOloLI@XMAe?QUg~c8uQC9XDd(7L;4KdU{HF^Beb%3ZnLToQL0VJw*7C5 zZ9Be8#0!pl3VVkaQXS=u9hM|4^3ujCTOH5SHt=cJdXhKQp5)Cpba@k5jvI89H{9|s zhc6X2mee}-SW~>87YAF(o)t0EVOy@x9A2{-F`K!&>GgO;*RC=_^XD%TD5s#P+JvMi zy-%9w8_f)dC)Qos>W3?B#H+lie`o)^7`m@kyz8U%LpWQdE#J+WhGjWJVgXe zIMJ|Tx;-zInghuSd382B*h*N9-}_)^XWOHHiG^670k?V3;vuN$jhNXHOBy?jHeqMM zFEb0|XCv-+$Qj#lbs>YRKuXA*Ba>hgp(%amuBO4C;X9#nfBQZIPr?^u%#e(22-c|V zv1Z5Be%5j4Lm#4!+mm#u^(0-sQo@ zCk@Aqo+ow2X@Vz4Ie|_~2Tpb8jaMkIuBuB|XA%8+b7N&`;l|p`2EWD0LFJvkBaAMB zot~S&KC`*F(O8_}Z)6KF>FaZ5z7qu@t6pP~=TeD>WeGSGzrM1pS1vD2_ODt|QklC( zR9IME--I{JhL&wZyIx`R1hDfp;LnRaUzdAT&s4%?8dWS zB;XZfRpyy&nXuFJT$_6lD^2kZmWwD) zUeMz1AW}E`NV-4>p5U9@RP|I5OGH#mSjEt391Pg=xztzgR*!WQBPtWwLEffe){^xBEpe3 z96xUGKz6R*S_&L~2FtNSP-KufVRh_K<=hWWk@1@Y zsWnDiJ;pk7)OecK5Myxa2>zrN49Aa)S?7)!#(88(cg_F2tGnjiJr+1t;w!T-QJ;ER zn8tfrnEq7XkBEz;2u0ZKjfD^U0mWHHMCFf^m_C;IUDV2+>o9Z1F|T=njSA&Pgm<9p z0us6vaO9}ZlKfIZJwIr-Az7lpOmGDAJSo{FSUKkm*VW2O1&X4wY;3wn$*GC@)I>G0 z!@7f`WbW%&F-3aE$)``(rn84T_k6Z1&9S&#&k-FyIoyf7N@yk9SOKae+EPh*G97d1 zlIpxy8wg0mC(6fNiNB}1jk`7zf9m)<*wqw|dP9#rs4!W5h9`v3QY*lDq+Crb+YUN@ zG74NqlijNAS#BEuEtc>@OPR6*#{!&hT5-ZmH!-(`C&QS!}|?Iv5eph0!Q%2T33fjYAg2fp2;I^%L>Vi_1hnza(N-J2sPTM&lZ{ttc@! zUXDjho&{yP8Qd1&?Vt%SZHI{{fbaIP5~yD|R6?Sh*8Iws!?vuBC(n!6?Sw_X<<--; zuslA#XZhU)Gw1NUQ1;k?w&j$!A$tyW?r?D`#d9~->>`*a#wTmFI{$mn*%xh5>)Bhd z#fQ*x5*8JzpoHl;m^wcfr0ilo`kQ|-cvsEo#mYO7+Ql=rux;7)gE~q-uFTWvIoUHe zuJb^b3mdPM9I^GcB5TX?t>OXO6UBn^h)ouf2W%(OUgj^u9rL%Gri|F8!KD|dWTgZt z(Kus8%<@S3gnM*QSbm9(3hB!SjB(03^Du3caDFFxsr25{B7r;raiL6=c~q5=cN}h| zx0L#wrt%p~-xc_IVUz#LsodfM7X?J^?jPW*55BSbknY^?vjo9b5wiPex$nW#>4sI{ zE5E_6aulwYEnXi;i}Jy#`di>cr{44!!#j8tJVQeDh#W9)!G!dPR!*OhqFzsfT^}C zb#o{qB;?y=_`FeCGLAh&5UQI)jvHG|kLg8BGjZE2wk?n0CK!)Bp%0TFV#1|S$ki>% zVx))a=8zccp?n3VIn;3-KvXK`4Zawdl}eU0rumtCxgq8g3At8P$lZ1wG>aH+g*<49 zvw;^xXfX%DJjhlm@^)WlDG&h`>bYOwl|;A zX!t4hTkGKvbKIn~cSBn)SmZTkMeB(bB};*yY!B7VTG~laI^5m}0xxmHTow^p8^a;b z^>@G&pZJtkL1_8Rqf~`lo+%C$mcZB0oBPvhqcK z6eX=D#eOJ`Jw8Km!oob?rJu4PqGECkhguP1eknx>ZrAcU7|&V>u}TLLpS!mjG3V}W zPIqav1eH`I$WI=sFh)bcE{h`EYo@uJsWb;X)QVhZH7Mh&AxM&m@$B?6&7r-ax;Z{s zNWPsFF8njJUm$QEfxHmHXGo|vCHyml$#9dot!*&vP~0vMduS^N5(a5r9IPQS7_9|+ zsG2xF-w!E405DXj+cYu09h<7x<)Qox#hrF>_G#i&eum=h0F*47b~zGZDr^UPH<{&7 zyV`p){F8$p3cXIt^@VnZevFNej*X7xdNahIU_nRoJt-mFT^4pt0NtCE$EQb0k58_v zR2s`;5aHYceZ?KWTu%v#-VGz3;cIEhz(>~JOC1)0XUjAN48FCue#=8M>+_5Avm2%x zHsZ)0p*ytvmm4;mI1wrID^9F-*l_)rMTkd$&}!xQXdf&yNrP0C$X3^zCrkrt~(hhe`)3F$C zU%v_ay%s|_Ewap#>t3)|U0A)o@TvgsQolg9fwjGEj@PE9M8h%zL(%ZrUIv4-sa4t< z#{3=>P4|2c_~sGj^;UdKy6vPDzyc2IIq;(g_yYfc%HmsI17X-QMtCH`sGTvtBeBH% zj%0ExbLwWszAou4zeUdk**b{K7D%5?31qce5o=iqtDA|{8nHbqjz{9iZnQ0X#EBF7 z-t{b>60MlhEDnNR(7)*i3SkH+g?=P8JHggg-E41b+0;}WCnX69*!J_U<#UCQ zuAAIji4KOVLa6hh$8m$6&~4L)#$m<;}%KQ@Gyh=4%r!JaOD`9dq{P%-RcMmo66Jhs|MK&bKWa+bMkG?eh}& zT3!8DDCxw>eUt>(n0N1t6%%GXb=-;xm!4qxZrgNymXvjOl>W zlR!bpyMrcn*r17Ht}o3jF5bO>8#ZW)^$HJ9qr2A{;=)^!h17Yfxu38&KNdOwP4*rd z%I-7xDIe@Z=AN5u2c3jcOssKb16iw$Rp@`SR;$zhnL*{1cS6U4p@~iq%j?!LUtL>R znpu0zd~yCY^99I7HRVR+RN_C#m__1I@G*T;sx*UTj9;l?Ou}&4h#`Rkmu?liC`7}> z4~ZY*>j2Thxj>gGey3gJ3cafi;{i*sXpuM>uU*vhGo0I@sEiSbGX&w8Ix3i`L@OXJvCwu z$H}n5_k~L%=5S*3%;^zxn2CZ{s79VXc6r1c?l|HffNFPc6B6Udi6}>+I8G(wppt}> z1Tz7o5o6m!yXFfMDC3CQCJ5RIql(>5cmtEvvvBv4hUFysgtST&bP`7OO!B_%UaD+G zR*NU0H&MJRDndi8h(k|t((PWV*wKEdQ(#KASFt+DHr0a@+hOhp$p1}L@?u`^6evK* zDEd!PH&DAD__y`iFR6BeFo~(QX-bNNiWtdhbZ*!6naHMLa9a^?Z5mYvak!s~$SPei6tGG-=RgB^Ede{wb zS6pA>IyQ!qyOBU{Yz&n0#>LQ$jZ>?!i=Ie^7@I(m*p@I8Ky=FLZXVxQn_1p4xzT(?%%2f+b9HWJV}8V(n_ryYm`8oO#$sZ2kzOJz z>$Mgx8nohF9qRd26YiC*0weK8O{lpJ+ z?z(Zu^4vE`50&osqGoxJoxV*?M>?U^V%p;l9E%cPe9>6CRlz<){0nh~#PFFW_nd+2 zCwHXK+-bOPkAmb!L2yuq>$(8X`wc1I9=aB;`v{484sJT*C3SBt%c7d|68T#7&~6t$ znfq;@yYk{`129G2`-W;Qy(?GrUep3T5c>&?N+1hy9;DlC>I^4GOnh@hpoQstfs5K# z>Jzov!57Cw9pqWaFM4S%i>O&_HSdA{GF$8}q!&AoGSD)<%4|#yuCfSPBw)7ntXE%A~=G>4#!ClHd>Kovqs1wH^9Xfej^gjXo7NOj8f5pU(a2;%F&Yj(=)*o z2V_g`x|-QE^NLD(FMKI^e%a-H?r55_gDi1N3;Qd*-d&$Av#7{JsUU;Xb?F-*FL9Vd z6uEFEJ8_3Ni@ zM-)b7K>nkrt0z-E`QHBaJG*)!u;aI|UEg81S!A{?-)gZ43)<~{ll&LWz{j-`GYrCx zXGNwJMJCqTYQ!u%c_SuP#3sew!Hpuy?x%|df;18 zG-9q<4t+1W{2TXa))*z4!PXYT=?mQ|_gKP2$MImL8EkQ^1x;dJtsme94$zmFm@!K_ zAq8l3Bj%Vd>@m{`aA(T$yo;mney}#lQ^lJ#Vr;wLk`VwUA=_k@5WP|a9>m~W7#0@M zE0?ZZs?(o?uCB4<;JEZ$MCQC`tbM~>xB|$|I0hM zD_OjC6Isos`=D;!^cm~ow&b&<%=5yEODPlzzr_*MYN+P9MAylCW0L%a%nD~RKOh~>4G4~bUrtw8z#QrU}ft)dAqWx=+H5*9z)M)pOaSP#j>-0C>7_WrP7rRQc-SHB)LOX3c!1c{Iwpw%_GYWQ? z*d@;_y|hY8)Y3~E8*){YyJ3l4S9vZ0O60lBx`$1OETTx+W!E6#@)L%`mnrST2Tmip z_l<4!!4=CT=`P&ZWmTHGba}i^e=zZ6*DB`l7$x$*YQduD!(-Fa69{HLQ3o$*MW&HP ze~_WyoJTcNRM`~eRrW+~*PHU{CT1?2v0D8kQRM1(N@F~Azy12*FkWURzvpmcc|@dw zL8w09-N3tbNBx(d;}RF&N}Q&5)O(Lk%qaufpWr`xlA)J-lA*t($Im!8I&sN8b*@Wu zm8u==x;WJKVC2L3fY>uoj6b2PL)X6MCQ_ZpadrIe>%*LA1#OroA0RuiKNzLE_ql81 zykrlWFbC`+aV}3^p03j$C00rd2fbb4R#GCpudNA)v?Egk>)^`rWv7VqiW z+@FIE@DOP$a(A&A---f1so>=Tyd$#49LG(}y~s@x<|CHcS|?7`4H|~76GjU`%ONX4 z)Dl1Q6NqZcO`wD5)MW}y*QPJ``hbs`B4;ub!Gd!^?j#TD0;Z0k7Sxe@At0X_)aM^P z1iS@>N^a05m_yk*cUQ|^ZNB`bNkDeXJ31B z;q`d`O0(Trac?fXxW=xymu7EH+cz$~G`srx8%xgE?dH-XV=cG)4ntJVztTO%+Wh*4 z$%BfCNevz`5j3_FnzrX+(@#b?VPqqyh_!=+2`Kfdh-gDaKje;`bu)j|mYFzcP9Le< zXF`vyc3yJXve%T?7;3BaXA$$p@KnqZ=?;-!Z7!D_X-6}lV-Rao#G9PaqAE>>_* z5i-$a$@&e<@{bht3s%CsEsNk?#1q0taJd+7C5h$^W4s}uva{&nhYr=&Pi}S(N>H7p z_k=;ALEdhsNwm%fGdZPlou-WXn=MfcYoeDym?^X}U~gM~i?ykd^1vo~v1w84IC%+z z2_9ct*<7BR-MluxG_$bSn7h{4cx{!;M`sj@ZOirWHWC`tYb!607c=>w!oLv&KzSMM z{Mgjw1R|M~G%Vki&Nhr7xkY*w(U!qqvZX&-MyIC>eU?XVMZ9}$etBl8gle+a{mirE za`{NM_4OAQmW$0U3%s9*W3OJVx@{{QWw*&;0lRGw@R@8qGWKaX`Jo?zibt7jO> zDhaid4S+u&PdyQ7NGT6po)AB}x3?$Z`hFb(km{F_SXJyFz-0p~|7zFg#f}b`JJ zr@i>+xy{Im_SN}p-SR@$r@%V;tb47jnhDMHB&S_f{lWwk>rG`VY**5Xvm;ZAq4pf8 z#L#cK{%sAtv#KS^=}8T$_oN1G4QSDPGTL)S85*W`8!*3Wt9ruxq;9??7Hy%I==Y#_ z;8b(ECY_Y<5kXPu=1fD+h=L$7GmN0;(%BsUI~s0>GD~R;rs)NICuCMLNRUT$wBNwP zyRmtp6S?%KYF4RARQAyeR@91RmH5azNoCc4tNBS3x=?6k%Zd}b#bdpiYRHH=uGDH7 zBH$yzyYx(cBpBU5HrHp@7FIXt3<4t2yx;_O2L|m1$ag^kb6-v(vfeFxTz*j~TW{~3 z|DgHF(HGtbTW`G)vesKIck8XtZ@p#5@mp`iZ@G5x*6p_U)?To+MSsRG7RkhJhi=4T zbE4+tapU2O8eY)Cfvuh^2jnx|mF7;&OrkcbLGVk{j+n#z#I?LQRia-}FW)RI&8&(N zy6%ivCK0yC35&M0S8dgZcGZ;?M2Tmb%DWdI7gdO>sAQW~&vKKS%YhJb*}W>Ym~QH` z6g*Oh3)yp@im|Gt+p2+j72-5M_(U6aSjc=QZluwg&}9WGVpWx$GgQps>@p`bt*fMo zY2+(FVL?yH=%^U!Wi?{iyb2BLpbEQ=OQGp5<3qz-0LFAr@$8BK^qs3h9qJ0CD>GNi zRiL|;C0bm$GSL-KQ&L15dClhFqSV0Tr6~?ovghk{A?6j_^ZsscZ!a6n9rdV2`5LW^ z19$Z^)mBiosAOGB34**LMjaV{j^Dha0(YAnm`4Oyq?DZA9A~bb@Jb6V922!M*xgdY z^*bk9Jqivo(LF9rbc(c)p4b*Yd!R&zx@`;^Z=WB#XNiveK)M^8J6zwlm|4+nGCn?l z)2<^1VoHJ(?*kd@)#@ks8oIFhsk->N8brybs@MrUygom(_UiJD20bsaxwZ&GoZt!> zbW_yxG@ZxtPPD2qOK@+RT#8Y{LaO)%RQ#MB@zk#6 z?XZ1vyUs-QJgv8{b^>PwLKW@-fG29yCWF8I$6t{ZV5;0{Sq{b;zLk)k7ysZOi~kYh zjodb1L?A5G+)5?3c9}U*Gsnyd4xl`?%RF<>iV#T>q!KTB;Cz4=6<_sfZGUh)VvZYQ z7hTx7Xywz<0Bf~0`=}Vao^}Ku>S;&tPcw#5W<~aP_GrQ0uSAR@qq%--#N4**9b6|j z+bpp-yh*~5NnZwmeOIkXvoPj5nlmpFt(3@Zw=LhPo5S}qE?npp1!VaEap-#%fC3@S zJa|&>dIa)i3e2#aS#oZ|H{vdHnj>hYWizu$R!!Q}>fr3m?9KVc+ya@G201!-07Wbk^k~fi zi;XHk%g)KAne~nNHM!uV)eVX2j*Zo7HT3q_>Wu~do~){&1ZFc2lP)?(3_Qo6mWF=e zWUAJKhgH2I2hXP|@Z1`8HU&JQ@Ef%Vx zgJiB^bCQ)wTX}~Kr!3op99C^9i3~o*8?&{Vdg}{pn@N((P%nJZRRCWZe`nfyiaOV< z>f&3My>dus7UWO7a?We&0g`URloh$3{butWZ3R>hzjE$SkH%u(4H-S%`2fWDFo`~> z@cq19@~S?&^xFDMiw*f`9IaVxD{?KTDR&NL^x~VdwDdS6cRvhpNK_5<4obo)3(kfBES^Ly83W?$S~ZSWhk ze6^+lN#v6~X^Dq<36QC=y18~E11=v=NWlm3Zr|MewapuPwG!u(@)^Z|wt@O{p|U$` z0_O=_q`fp*-!wX(Q4v$3#3 zr+Kp62j$qe_v2f%Lp?*F%ggh#-C$)|pmS>OT6S&-4#DG}z-OS^iKA+hKYt1=<~EmB z)t)yGt=?dLSVFG9xUkw-U#E?>gqCk?433RorsyN|=zag(HFdTqA!h{^JW%kAFXv$HMC`d|U z=E{RynJ3XZ(xS&h1{aoQZp=3p7q02;$|KE_R+3ouHqJXx=M!|Mj)yE8^Gny}=Ne1% z8#hz47w=+QRkM8msd?b-0Xaq(nYC#rF-T zmS$dUtj(`)E^g4<&60-lDdXcf8zk}YY}%& zsZ@hM^-27;x_NDJVfLW1`c@?Kc>Gy)7(${-?MV8aChcl7&kd)~;RrTX;My~geQGZ< z({(R$#K52zY)en2$Jt`tt&fe3PL5tCGKi#7tCV&lh*0ByD{i7~U?lZ>+P+-vY5Vfy z{n|OTwtbN=##Hp9zPefF(T+Wj+}~N-aQHRc*L#N_6;9u*jDJ0NuQs<|egxQ8c42_dP}T9Vlt#BhcsCLE@;t}x;m{&sav8G4rikd3XoI@EaXeA zuPkGJ8P7PUs-GM+6nb$Uk2nwChq9+eAXVj16RCKaJgL78*Uin1S-tViwI24cs;*Q& zLpwqp%j8NuOv~5QwJfOA!@&N~&?H`(+LdD{yg#j}S!hJ+V0zW0he_=!|9&;sq)=3; zSbEv}nn6NoLZwioGWC(3G+Z~KJZU}Ticv9Lu4u)cE9GanZnmU1>@Y2y1uX|}$0}_| zwo0H%qXDuxy+`4lLSp3xq*QgXAkbe(c#&R{X$MtsfzVFEOpZojohH;Kv=SPc+PFB{ zHANS7?c=VfOW=dC#DDAK0_QjL$=XVkDo!-7s z@8!bzxuE_%p03NNUQ^wU;om*!Z6E1LZ=2HZEAgWlWpc*gR(Pl^lfl_4jNF*f`MJGq zB4RfpYAe+&@VejVL*}RzTJ|;@4Wfc67=4tU8sgYch$|c|1zuDMBW6d;N;JQkmN+fL zr2y9L$!)3{R&v~>f|^#GMOScR7=I4B3z(j3p~iIjXvbMks;QIhY}TOqf!?T!$wOoP z{NdhO!h6NhH)HO+TUULb71ImfCDW_-tG=8vp!*5_v!_}1(Vk}6uj#Ywp0E1y@Hzb4 zM?E=Bmt)O{*+Jy6$V@EP3lQ=KcL~3#SAIG13Rix4a`%lJ@#Scee%b!^2w~soYA1nHyjewrE}B?CvqDJmdv_Flag;7X29cBcP{*#{@|d)y1X~Ew znQW7Auslx&)8dc0(@}4-?M6-|w4!9+Y`VUMXY5BP7FXaiKZ!>u%Cyx&DvpL{7RU`7 ze%su-Ff6Ia(M!XF=I<-+?d^?9SQu##L(1vcNxp-Xh=oCnz%u(eI}Y`~tDS*zX{k?j z?let`5M9A48~tvAqy}Z7Ha(UKl6!VP;;ICpM4X)}6Q?we!0h{wlq>f^GiV)^d*U9P zL6E=Z8xM|qAj8f|Zs43VbjY$SWX#$5=F74HTrKT*Nvs4}zevb>J>DhGL7bCi)rw_` z5cy_h%an~&dAC_&Z+Akt1ES?oJKhB$G!wDqCxIWglMFlt<+NTwPXchJCjt0f8BHh+ z93|ac);d0P95--WJP7~^#S)W{F`>i@N0t%g#UlE~Z&g!tMAtWYyp(8{MN&NJ-RY`? zXntrdD{JVi6Dot4mf%#ZS%@@Pd>+ zcOy%7gR^?rLs($PJBRGcx9{5tIV3&+ZRdz_kiQ&Zf@iSA0auydorKX3vT#PLw5Ebj zoj8)ps8%PdxQ8{2pxc)!w&0?VLx=3J#KA_nYTrIO*m&;Iyh``A)RJbs?5Qz(0?~w{=+95@iE(cWK_ZOKDauevuLzZii z<;N5#v2hhT2V%P`m2*Jm^`yaOcgo);EdThpx4l|q&RL2Q_U?z~)H_+Q*6W#a z79N^9s8`;^4eGq3mJX1UYIhsIE@JIU?aEl4{wT3lvNe{>STA8&O^wRwS4v!^0YINo zl8PoFXD!~<>}L5~Vc==Es~7w8cXD)IjOX47W8ZpEH`jEr(3ib#d>TgWYRKPaQSzYV z{QUccasPYEjr;HgEg1LT)7rM_Vs8vnQYUUt-mdbF*QY?>6Z{`N&F%S~=Jt>4bNl{O zmKig4=|QeNYlq>94?N3>y&xXAka0mNc;Naj^Ah%=n~az@0y4+12Dqtp&5G5fUf#n) zpSzkZNTcm$xb9nd^OztwKgpL`$pHh?W$I4XuE6Ae<(-5);3jvC;nGPfDI|1^vUsG0 zj&@Ntt{=__Y7Ckj_T0y_n%@*#cxHVcq@lo|95nHNnuih_`0A3u-dQZESRb2#VrtN!hfu5nwL#?!b0h&2?Qf2j`LLNle`6Nlg3?x|ooGjpaUI zGrE?E6$}dkdI!@&Cp0lD%p@=s7`IELl7W~_jb(S~fCFU-T;h;7Eb|0YND-=^KP2+51>LzZv?KEdr7eCoE(Y{Ng*{>Y37;y34{R7%}>1s@0Hp11TRgQ^k!N}gt zm-&b~-~F8nTtmUP(kXDh3!fk;9Y>CE0DJ?0{9;bT`>_|axVrJ}Idx;Y!gEJ?xbGRq ziAFn4c(pz?HfhSdPR!Qm9g>Ar%1ojT?f6Dhjaqi3&63EqWA$(9n5M3rk${xZlK}d7 zPXg#qbODr_1e6FuaBVm($4P~4ZQ(7nUB=y&nHBF>lAwZsr3hXv7g4jhZ@x^N;#y0* zTcf5lwY#{&(Rzi0_Of<5KGNoRlJ; zld&G8jc8vJI1fu!ka<1HoELkNIq_X&jzw|$i&7`HEsw&kZmiE;gGv+lOo<_fgo zTBQCUsVER#JRG?qD-)vS9f^c2?Yl^YX-Eb7qol&!C%&jTcO&Ay=l<*=j0+}rfwjJP zxWTA*-IzteH(`DsH*hwryfg-@F>66jPc0}9bKIcJ@|=uY$H^+rk>l+^D{)ShkXaLY z8>gztcBkF+E!Rt1c|?{;^AHkBA$GdTcJX?K?YWwD=TTWo%gjXcDL6r&l_mJ;eb$xa zE8>N2e3yu-(xWCk?12!McwREt^6Vf86BboPGn#bj7fC${rNy3v(!bOli|Holy_jy+ znJ3SfMtDR6Gw{8AbNS^pdADm;I0u_AyYPxJ<6sLrHa2R$;^H0|vyu*;2#GuPHoWD6 z<{QjTOot`>1=%uk8LQ$9v4`lEPp`kWbbV#{wFaU* zH5zj(OEU}0>Tq&^BW`8x%;eQuD}r&kDnU!!6L7Yw)}{AT@Q+N1J=UyJ;IbI+)wNi< z$erN-=8KLr|NZg-=060MESz5sr7MoYQvT4^8`ayM7M!J?7M%Y>*MemTtz9?S@4oI3 zuUM_R{E=Qx)@G#{G0UmANd+M~B6vD^;<;qG)0V}%N^A*Ga*Qdnx@x|N%-@Z1AY5Tw z>mEg&i?O1Nm(8jlVsJQo;e27DHa3~D1K#twq}W53aj+(8IS-~U=A>xm`8M5qpVr5k zv{Y$tl%+v-h~INEK@GUNPyBpO0}i>RSogI zrXE6eQ02*BtZ51e4OkhnGtKD^izrzjVG1k5CS{&T%?F`P!DT$qGzDlNTJOx<(!z2{ z15oZU$e9MtsRA;_SQab!p6FBZ$+HSS$*;o#EzP`4yyfME#CnGT5S0#urC?6lmVl6|_9vP=s8qOfv>gMX= z%FJA2iQ@F8?MVuzDL}CBJg?$T?Rj36MvRep<__rSWn@&}ENiGDI&0{~QlFnA21Y`y zwr6;_i%v-Q2$VBGzevFAt_t?$^m-J~pL2Mx>Lfr^S7_r^Wqyk7==6b%Eb~ac504W=SVZ z7xh=Tqq1DS>7YM}gzFMf#7|rn(*{$tVY)s7h|$Sly4*uj@38KXg0zFKBE@sZc4{Q# zZmseX=-Wwc@rEAe?%GEAVtf2wSfnO7<5zgD>}3$Gq1I<-Q&?CZHuMhspZ7cYHC zg{`-F%W)_uZPT?YQ}0Y^6QYZs?n=pq)-?7yKyk(W=au!18*B6Hjk#;3oTc)+vW|l2 z!a9;v2MH!lpnKL?rGz69oQ4yY$+!6P)dy&z&r418K!MQ3GVsxND6X>0?~fkxHk&n* z;6Yu{;l6QDY;|zv96E?wDMMM?R>E3Aw4a8erhT;Z0G^>Y&rNtZ zI;ILyE`Pxf_|@yP^QOb%og@hL(;Rcxwa6AK-bcnF-Hd|0n5E`V-tVq^X>BTbuHU)M zop`Ez`d4`2{1Qt;F4tFuu#BlL8iX;lc<@9ETn~{Q2#y%)D(5gRbEI^->i~C=;S;s7 zn!2&T`G`Z7*ipOLCkq?okrJ`gm6qA_>X+Z0v4^Y@?7h@~xZCO=azfe-JOEd_0ooBj z4h`~lSsY^{Qu2V(5r@LlbcL0x9Vm0eY07=(Ox@icLptI#CWO6ScX^0%* zCV+FVtgOwguFbDw)mCqhh*v`8D<0W8vqhv$KopT1t!$CUGp*>|y@!^hML`tN1$gGD z?SO|fO7>U(@PPf5pW78pRVpI-Oa*Zo@KU@@yM;>Vby}`}l|t4xeDXMK$S8| zMZWqlRvW!EI$7DmLnC6~%Y(zFMHMgT3k8>nJ#D{Mds--JN4u>F_u`Hn_zCm%Co`lI zHZB(Iv1aThV)xaAADY^4(G+HJ+;vS*5G4jyM{1~=zta5-85g@{3qka>mR&e5i}*n^v>w-iGjc0E_7$#hs@GQoX=|rXPC!+N<&wmwXs&&}uP18QEh^ z`RLa1v081a054y&O5x>ev}SaDdb&Av^RgGbIdx@oYOXVGPtIhOBZSH?qI`DlS{~z*e9i!6Y5rA@t7+g8VGUfyOE{5^Mu~o*6<82B znafstC;Ir_*c-3Eq2xrt$Teg#wLQg~^9)mK)KB?ZF5EZlo zr{ie{qi1+Qk&FRWWgpF#Wm>30&SMqk+Zi))H&x_>(}blLcUx8c@1<93@Fs@9&GJ~3 z#CGI{noHB8oRuni=8JkY@5@&sBjn|4dP3Bc%g+$|$$VvbdYu)Oi1dtm)uZ{sI>E$H zgJPLu?5FdE;@GR&AcPv+heexl>{TcSuTCm5K2=u14%<)5KctmMMyB{PWyRyzYuIUQ zfHPVJcJ>s$h`!$rlgQFs#T5E7C*xlBSib$X+e}eECCTkJEEB>g(xS|%> zB#2BnS4eLjA~yLE!x;F^d>E7Sr1TmC*M>O&zLgK!ahe~}^?z1?;9G$Rg%lQ$V>ERO z=L*lJ8cSv#SEzDGA>PbPPW>j2-1BK+&uvClw6Cc>l}^*WqKoKKzXi=xF5AAOE*_pj zEut%>?shMvcw{SqkmrL?Q5E67L{A#}OFe1mzk835+s!y_*ROLl(-V^U^a+(&&x&Jn z1rOe>2c5`f<}#0RXD+Fb$WlY+)pS+Qd3MRg0vgHhtNLO!U zRogzX1<|l7QasC(y3paslpO9%V<)2TMaTpRwYOI1e>K)td1I6}R_9H09Z`XSu2R(V z%aEQaNrtzOXfv4CAqu5)I!3VqHHYwevZezS=a6g>lPCu)CJ{aBU3vL)hazgm|3~Iu zcG2kGac%jLJ*RCYAA-Bh;{2-5OO+Vz0Z8f?Ut=_tEj1(LZkaqHP54}JU~Pq={N|txPvQ^iI~}oG9Tq1QxbZ)#Y7H5S8etTKL2P-b`=ntQpAvQB`%|LsetzOLNJm|t zeW}klfuk;*cMS|0#^AA&;sopzl26NHu#4n*D2;CfH3nfok0W}+ z02U2X6;Bz4ap%q*qbUmOXzUt>(KKMkG5Ss#ZyWDHZ~6^m@D6B=(>}yRHlDygp28oA z=b-WSdE-d~iP_KNC21uc1sMgFu?0UE{2QNH?Hk%Ox(LjU0kh+VG5A>w&NOf&R-jGA zKtJCQ5J!^QE=OU|Fbo9euo8QF9BqKVeo?f6?_V^Q#;+R2-{R+;)ayqKW8jaE0`%>{ zK89XXZ{GuUd&V%%f4EMbZe}}fnL{^&I5C&pohW#Xd0w!G7|U}juPhIJ=*-Cr8#mUO z?<}!6wpz@*(2iRldfG6~f2`i}f~Mt}nfzjb(#khihdy-DFfN{48aMB}J#g~5=U&F# z@RLw1?eT|2Hz!3m!8zB&@1xpp9P-Na z{QmPhckX;l{Qg;jSsMSkVSL^&ev|(GDlzhJ8Aji)8%E!67{=h2!Ngz2?)*4h&G#WF zPF{;#r^PCBE3>e^99RK`M28pv8fue&)U$jz8`eUx&nR%#zQF-`oLh zKk@cW9R0PJW8T~kSyXx1+;yX*V|nJwH)hNiBDPyMYZotKnBQ3qgRq>|Zcj~2O$_j# zW0PZ(IC*&QK`lcscznsVqX1Xt%-J9cgNV*7&l<-0r-7sv(gf}jQQ&!u4$)8RT^>?o zlY}A>bfiG28CB|XIiaS1Z1qHHRcap=tK>Vlx~IH&L-RHJA(CMUJz(ero3p*xjM z@bx51pv$8Z6N*6R3`oAu-!Y7Ta>vL{=;H-)=~Hp6S8^@P%?oOkOz8WoB_-Baj^RoN zOvj)*t1$V>5P|w7efuRmU+%LWj6-DvUt^ zih>yXc&W<$pwNx*{e#BR_;JJdk>kb_#?m;p+wf^M5Y0*GJ&%Y}Aj3G*FVgz6u;V90 z`Uwd;urfpVA+UNppXZRQlKCSWoh&_&4^U3=t!E*ZK<*h6li;UEAUkZ2q`bn6=ZvNC|Ete1{#~D8{Ar(Yo)T5Lkl9|) za(%s0hb2BsDltp&mQjpO;e#ES{Kk`2;IVUtaRfY!Z}26)!E^Wq*3PyaawE1VOeCUI z9Im`aYAXYDI!)ixzdVDKu{!AGFlbbZJ56+vNi(zCg< zuPh8&>bV}XV#Vh9nmP6gohNf;d3GaaY5(&za1>PydEDYo(`Skb`P^ORJAvXb@RQ@l zJBojaXl}eihi+~Q0}C$vk7!qB&^GR$iQkx(-z|Rs>wdsUZ>QG{!}zCSlRj=31~!u4 z&aI1mw%F=}X8*u2`o7mNjDKht#`hV9aosSCU*jSOzV*f#<89+j!!TA2!}tKOFbw0{ zu)#Epfw^;r@f|{xeb_Jt{yK@ww+Bzmh|C*?G4Qje4P!xM{+EU^_{57M@g4LFNp8k;`=iI`n34R3lQPQ4C5{F?{7io*R&@f z|2ysX&%t=sk3ZjyKi`8t{{^fPNjuz%{|5fKk3T+@`8@HSV;B#A;R|2*ApY?~fZes6 zApSvs{Q&;_S4g85z&{VKXmxn|A0YEn$ZWwX{7L+?i9eP~Tf;vW;VA3g@<;KyVWl<> zL-%MKro6=6sS{#10rxTd`6&K;gwz{AY`8mDk#Yrf_y^W84YCg-Ik5jwIgo5b&w-JS7!Q^YkH$_j%Zf&K zE|j7WTnL5c5E;6%OF$ z|LIS$GQMjv_5EFCYKmP?T>t*Af;Fw^J|;#gT{UtMS3=`+f@JKrP}1bQC#{Oop^nQ` zXyU?xZ3n*3Y?T8&L*(G_PZmJ+A{m3ElqfBoPL?D*)NKJDQEXb7q17LCJe7=k>~>^( zeo}S)>=wgrM};&zdW*+xWwlVOWm+Xdj?%<=i}XfroaB4tu}VyCTuRXb!CF=vMgi)R z^+Q{0MOKI>zDdcX00A-=ieNUk8Qe~*gr1zuw!==FwPo>Q{x-9`WV?I5i->Frrkd>%_yYk5!yw_6$-ZJBWd`kXTs4q- zR&IFotT@_5uB;H8B`ef7sz6$%BLEI_5KG))YEbopdo5RO7||B>zq02>tktn1g&}lj zx77~AD7d{}Z84ukmYNb&PGwRJ5=T%Y&1!EcwuW)S4ROw>b`_Yq{EXanaIGp)TP2(k z@thr|62Y205uL~Og*J$?WgHi|(JlE;bYRDI#NmcmgJmWX1y{>Ew-EXsan|#7#BC7DM zBy5Ljwow%{LWL@zE%_{|T8@K@RTV^TmNh{x$h>rmOZB5fr1%4ai6qucDj7QkMowmI zxd^x~>qh@&j-O6EV2WfnOfKb0WU|_p-%3Rlh^$I!wPn&HYfm;V@pZ#4_#%Th0hbA! z4}Mydg+B&Z1|RGrKTZA^Z-3sv1^^BR#&`7@eFMhZef`GU#^3KV`hL?ej34VW`o5>n z==*KMF#gY@Mj!Tm-+tV{re@&I9Rt)DJn<(-je*tUhVg=744N-XmkBz?|7q#TfvrgY zRuJJq0+>v2*eg6z2FdG2kO5SXsKdhmA0722!!Qus=)Ht`9&KRoIGuFjBt6ski8!)- zD><-jjnb06JZqmtm%}JX0>!8@k3S@t6`yj1C^diot#WpA2~K32G7Z1iPVp9zmsp|HF{NzDQ7>6jm)u+0uYT z7=~4d2obwPLSs^dVHhB$NkkgI%)x|1As%E(rUJPz2{YOZwTQITs)rdBA}wpU1G7d` z)pqE`)hON#tD%)Hv#|I?Q`IQwKtxvg6s^X(nu3*90}0}At7=85DH4lHK0hPr!G;9@ zKTa&)R-;-5<1@Fl-AwI6Wer7^-%^$2Fzqy3A*p(jj_=7LB038jW5?Ill=qc_vDj|EmXtvz%w3U`!|J4Zz~c4N{abxOl>tW_ak z5*9(dl9bAkI&|A{JEM>0Y7qcib|qSmgw5%=5PpnwwVyZ+_)mA&Kyb+{UWrzo@P^yOI=$>E8b9m?@mKzc=(JBcJ>WgC_6{#k{WOYT{cisLw<6JE|8RHw!+=eQ$k6M0%ds)$4%!bK{d+HO#FO7 z&haU^1%IfDd4AAQf=?G+)UwW_`OM5-ET2i;mE;h-q1w&v)}S*;d5MT8AhJ#jD~DFIYe z7B_UMZeSi#o@-b5CM5}?T=}6=7+UF*O2XP9!oI2+aR^YXF|zi$mXJ7PP>7R=S#4D- zrfRX)jDD{u;Mx^&ZBtSJ%#%d5OIO695dMwN%i8zL#?tto_Tll-f7?fgC@?Pf4HyRb zQV)vbfj>TKkl*$ow3UHRKTGP+c?eG7$&J%zn1Q(iFSXq9UE9mqVt@fp=a)4EA~fEe zFvf`teF!dY7KR%v1b(b)CyF@d*;RWRK#;?*6DUpq_dv(<;LGc|Ej2elJDHK2BYK(G z4+1q+FnRWpP(uLAhpff6)p`f*O(iR7L-+|?WN#_Wv)w(dQfi;?qAlBIu>uBZM22nI z+lqu*f$R~Wmf^UOX6T}fy}c^U$*PrNj+v8YWNRamsX`gqKpoy2uh^DO9f%f6ZHr3+ z_*@iS$2a1Cg6EEZ#TYb>eZ@HcWR=cMsJ zhpJf)QH_|boE3mpGl{n1O5ACR>magm2;Nq@b-^%Dje*nb#56_{lFTFM9M6iGQm|xB zGm&QtvJ4hTlxZf_kVS5|t($E?Vv%V%yDUl&!(J7|vaWI)aT0ZGdR{?REirAvJHhgO zt*C|%U+go5tPq!>@nl}6d*CuJh^%T7gsDKs*ib6p?Wl^t0F>^t#LbyuPzm%s)=?@m z7E4NRDdPYJMMVY^vC+|*eiH*UD7hzb2OUhyGJiL&3H!lE1bHC5q_a4NSpLQWDEE_y zA@>nJNw_C}3jyz@$H&LFaHP4uev>XC!EN}QZAEx>fHrKP4TEE-;KTev9s(LwQ?i`j8&2OU3&aoP`x%LNd!T>gd-UKXQ5JSKjFgQW1s zxPM%vV{CE$iVxa)N&NnkBdBv}{5N!71J4B6V6!wjz9a3#xuC|k? zEyHcNOmMzXqv&UKRG76<{WEFx`D|({%(Zn2Z9PJ_vBT|fdK`a8UEf8EX4e)45E^{C z*r3Rz_CB6#?=;#wR<*(|RICIeCXHnB*A}qspHIBC((PiL%p)2khAn<>- zh`$CweRwI?^22C(kVYFvMriKwLUYJL{b$qqkwg_{rx_n7OcQ)M+IPoT8lUJh`o{Z= z^Cx%X1gL(y?r7)=y4-L3Bbw%WPY= z>O1J7Wo3LEb9tG)24o(}wL7tEXAF?&R+@7wh%0pWQQ{)aw7ej)o!Aa5ZA(F9tL|t% zklCDe*PN(p4*DlCfvGA*6gd^vqN9$)Qlxut5y%$OWX=# zaE9BF<{*nffL$l1`olc{zct0Mm zIL-8so$LjB*)+@`N(;kEGYFCxfut(9oGpn|pl_&KreSGPB!n?CC@h2+0`ev1Ud!lD zYX1VF;^KO&<~;aLJ2R7*fULMRo7ENu#Jx*=5A-dKzhxMoKVm#?$bbg=f?uT**v}s^ zo+-_)Pt|I*>U;G(H%_Ac%2@g$H0T1k^{w!Nz?D(M=-V-jzHc*(zRws2?qm^^HK8XfXy_maGIkB=6SC zG>A1}biwS3ncM@>h;d7zA2{p+-LE%j`NIcRV5}|pK%mLrs89X|e`2}B2eMrL##O`dtii)#B-5+fZ)~h(`n2{Nx36V7PQK;utJ-gDx@Gze?e|UX_k#BOMeX;Z z_8Z$rSFBt}nD?Y!h zwfifE0WWI${Hj(z9PYsf`24yCkL@aW0w1_jNM8E72LI1B_}>yv`uM=*Lc;%!2LHPn z{O@V--_YQ3V_f3%2O9hzYViL;gMXzTZPD#1#0z+v2MvG|1-VW?rDx%u6OVP!C)1Ci z$Qc!=^)#~TGE3G*h`k53okbDVItA#!-TA@Ck^UYD zPgvou{ooUno@sp;O_)b`>#7JfaS=tnC({I_SCRg`NWUnXpmaP2HTbz=`ZUsUr7uO5 z;6H@)5u{IN>Onw^!LefcRiyuuVm&iR{}R%#X6m_t^q(!J-$eQ^7Sk7y{>R1oUqm{L zM1u>N`WKOYsR+M}^l79oX5hac={CVXr!&&$kj{|){l^geU@TMW2ax-|VkpvA) zeVMEuN7ky~v@d3|egawFE=qk7Au17ihM43hk@cU6te+tIOk~P_2>^dsTK3Dx`WGVW zOH_6|Q}(9-fanoKmQ2=HkOjpCSwEG@`YN)%Lv$ot>SvJkcSP1#@sf$^$k#yUE!6fo z9K9VG8IAFRd90=fq6DPiv#Q`%<;qd!VIjuK4k-9vJ{Rcky9_06tDfX98TRXm! T*$8oEmaH^e74j++<&FOrk+eV+ literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224231651-Config.rsc b/MikroNUC/20260224/20260224231651-Config.rsc new file mode 100644 index 0000000..8bacda9 --- /dev/null +++ b/MikroNUC/20260224/20260224231651-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-24 23:16:49 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224231900-Binary.backup b/MikroNUC/20260224/20260224231900-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..342c4f1ce705da6b2d425b9cfcf8390b6854b894 GIT binary patch literal 307416 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 Yp|*B>C$kaa$}CxFwkqURD9RiEFW;p=g8%>k literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224231900-Config.rsc b/MikroNUC/20260224/20260224231900-Config.rsc new file mode 100644 index 0000000..a6d6a51 --- /dev/null +++ b/MikroNUC/20260224/20260224231900-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-02-24 23:18:59 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224232005-Binary.backup b/MikroNUC/20260224/20260224232005-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a3552caafb510e5a32c35a4458d95e8f0e1bf71c GIT binary patch literal 307416 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 ZFQK+}d?&LJ;>s*pX|^ilRVd0E|1auqKnDN- literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224232005-Config.rsc b/MikroNUC/20260224/20260224232005-Config.rsc new file mode 100644 index 0000000..4a12bc1 --- /dev/null +++ b/MikroNUC/20260224/20260224232005-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-02-24 23:20:03 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260227/20260227162307-Config.rsc b/MikroNUC/20260227/20260227162307-Config.rsc new file mode 100644 index 0000000..f1d59cf --- /dev/null +++ b/MikroNUC/20260227/20260227162307-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-27 16:23:07 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228043316-Config.rsc b/MikroNUC/20260228/20260228043316-Config.rsc new file mode 100644 index 0000000..98473f3 --- /dev/null +++ b/MikroNUC/20260228/20260228043316-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-28 04:33:16 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228044001-Config.rsc b/MikroNUC/20260228/20260228044001-Config.rsc new file mode 100644 index 0000000..f7e5c9a --- /dev/null +++ b/MikroNUC/20260228/20260228044001-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-28 04:40:01 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228044730-Binary.backup b/MikroNUC/20260228/20260228044730-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..9e54ca5a0ce9d2df7173778adb5f492de424ac1d GIT binary patch literal 307416 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 a{Uy}aj_+hPLR^_8E6rAgyb48m8Yn6nRT?x< zG#V;O%FuuY!gsB64ymV}r}zIo@B2RA_wQV;z1P|H+I#JL-^1_z-D~fYa%gYS!$K?& z2LOapj3T+AVSd3u6951x0015cK9~`0kr8bbe%qdi0sxP~|DhoU00`oS8%2ill!Zq! z5v~UY2M1+^?b!eT6JSro0B`^W#DP5#3jhuPfJOm;5(5J$aWDW-U;qz9zyNM=aBvV0 z1~h;S7|_55GW~*N`DY%$!Gnsx-Q)#V6B-;5?ib`^6v6TdF=F$4B!!n{EIct>8v}cy z6c|9s!+!7_sPSMxPie$Pcp5Pdm&c3<2p`#&5MCXJ8|la9hB*rl9w7r5g#BpF?4}iBC#RUN63joRw z0I&$a+Xqm=0DuqxfEXCyUlY8xr2v3f0KjqpzzV4EQ0-R$c@ z?E?T_R0dk5Jly6FjV=Iw4TAmR0ay&Tgu-3J;36CVJSPGGTpAaENC0q|Yyg%3fU89S zhynoDiUA-R031b9D8m@oZ5cdDJOF${TM4)Dz_4=20H6U9;P*d>ZlvB!{1v?+^7V$n zqmZZwmt?@=khunA9+~+=y`lV2Zz%swy-E72H%TW(7)>#}cpHJyfbaB1B$6BMOAwB_ z4FesXG_WUX4-Vj!)dvS~;^N}s9T>n@k#E%d7fpDpeJrm z6doS+2AVp5Ke>_GUh)gtZs}n0f35AP|0lIwAXokk7c{SqxZ!1ga>Erl!EAqSs6kXH zGuj|BfEyNO09D|J8lVbq(IGhn(f=C_5cu<-YQP~m1rfdm2=)`keHM>16d+*`#R_8& zTw{Sf5ypI07&kO>D1v^!1KiFIWCr>1m~1Ya=L5q%jCU~D!4C|EYQnY^f4d;Sq6Gn- zukOO&Ch$A_0Ivq@iLmF8&xCtGOn}Gm{|%!&$Cn*q#18P|28DYEhlKkD2ZcfK(mgmh zXd^sd&*0#onXvtVAH4*hO8@{H;W*&+puhkQ_Jb!dK?9&6heYvs6Lc-?Y^`QHdt18L zTIvns4k^Jo{W#v72tSV5cZY$e96pRJ5`_?k4`Xj;@%1RUp`%Rs?f`I{@Bor<91;_B zXE-=H&o;BS8qw7^I4nGf8OVkA#wRp5A_Ni2oGiRPC^?F-4FL#2*oN0i6}GDZ0OYUd zM!|?9xDhZG1r6X~Ph1)t3PfBe05q_nTqcL|qdsWZr&HKRW@I0cC82)dT*8k!VPL0$ zLH>#GBhJE$2ne7GI`Bt4JTffoP|xN^TAXI)h(4k$Cfh$E1R}=(HYYqdg6#|S5`L^l ztgV4PF$e(EVgNuG5V%?xsr?~ngt3nc01hVx01tkFK^F#ZJSqe(7C{LRh$J#RasZd( z9UkiE)rY=M10G6)?-57#fye)0AN0@rKs)|nAI#7Dz_EYd z2Mx^<`?b$dPR$Gnf-VQT4vx?*z%@tcW8tlo1~6q2I(3*vKu3W`^D~H{U<;Ew0P{yc zfTtG5`PU8baslA4H=yl_3jjcI1ep+YqbL~w z_*x|o07?M>=w_f#K`8@(8Y}R-;1&QVRRBz_`0|1&T^n^43@M3f* z1HPwr2LOje0N^29`@;YD!Tbuv&*ktd{NWcY05J371Pc8l%)nqK8VmsLxi&x3!<)i% zOciEg{214b5`-+c=JOl(R}MRB(XS4hZ*u{k00A73?061l30LH_;O#!$K_pX9FR`dG?!TH{cc-0B*vyI#dinpGk1{$#CHaPbmD%9nrQL(Y74XwiwYiAJMiS(Y71WwjI%) zF`}(IqOCKcJz+#!YeajLkfvE2!HwXCM~863qJ(ziEM#P$?s^K_(A0<8&>R;Ew?mY* zK-lgb92{f`+kJzBgB)QSQX_0(yMJ(SFhJObuwdwzXQTjdM%feBV4zF7fCeBL1Hc9h z0BIP3@lU`2)J68E)x? zi#`;)|351Mp&-U~4m67@z=tsv*2aBX}JM3g8t8D8Xnm;0{TcuUZE|$&gR-{M%)U{$DFo z89u8Q#0@tPvYvmxa54Wp;bQ+Y3M;e3FO@?p_IY~Rq} zpx}tGA^9%&+vO|r&y(+eNO`4wgTuo@f`=Ug>+g^)YD6T%!PxrG6R*gBMt$W%*ozG! zLIQ%BoFVPy{2dZTkCZS(EdOgItNBsetOJ0O_tKUC$26Q;p1ksN9d@Z0u8b^fFV6<|+Pg;}#2T;KrE z5Qp;yjKagCoe(&S0umySiV`sJqOb+oTQr}P;FC2lqvx}qE42Cb6b+yW)ADg}p#>K( z9fB-{hFBOk)Q=f}#QoCg3BPoD^uK(10wlddnVd+D5x*)l#8!C;g$37Mz@9in#0?SH zQh?8A@HvwCXg-;Z$3TG$)7g;n7m!(enx4;R$-yndq!vu$@z-E39~u${?~;Ix6MSGz z3Z4XhAonB%1T!XJZ}iA76XB2rvNQ+?_VF7g+#nkTKX7dzB;4RU1wP+CJP3XX1x{9h zoT5l%I0508$-?{sy~DWSaAFF-XaGO%{H0*+4(y4Lvw*W>Aej%VT(C;V*A7Sw3Ff~5 zJd_w718IFe?-M2D^#Gnv-@(CXK-xkB$MXvfgsvF!84+RJ&><={Rd`k?oS`<{XQOaC zS5WFPdMN;olz#VI>FN3$z{pxC=UXpg(+LAkio&+-U$n z&{$Hm*;?<+mz#|%bQLxA<9rsR-sx8~yrPm;UGMRVRCOAq4gf*Majfl|qwnSS=R0Iv zqpgkAfch=M>l>$qoU+V`(>C-FV6Ev!)LKK{zx`ojhQbSSWe^XDU^-r5*5B| z_{I%uT5tl@fQCRe&O4+tA{F|QY|>WkBd0#fnq{duz37ExdF77k9{DG4HV9-B<)zj( zbw-=g)T-Rn^N%M;!qMRD{rp3NXS-OyYQtaMELcSwzFFT4NCXZD`*lDuCuEXUmiIrS zx!Emv%>gF7-pz-Sbh}SX@!QtZD%5YOY-q;Rv*a?A3ZY!dZc{R-fK@PTkZ-Ylj+ zq==yU88Mm6A>MeXCJEQDJSZ~6)bo{+ukw5v6!OzD%44(?OddZeZit#o!hgB(N*Vw# zlud_(2J`#^_)Z3Xo(feMuAc&Xq9ULBhn54Ul#Lm-`~j4<(9ED3zNxMAT?vR@Aw=F1EncHb64$-=b-uqU38fJEkL{t_Nr=+0545&)D* z2q;ayOXQ#DlmyVg8iho#;6yr1NCXR(FT}Ng1;9cb- ziJ=L$L&^qKVyF#w8fwG+pr)z;fHPPb=r`1s@Z2`sc8tvSgQ~;kh6WxGmNvBEL4>%+ zNjN0|s@e{yra(~bNf&O1t0-X`0*wwKID)$}h0}!Kcp8NJz<-wuOFz)}JQlX0E-i)n z2?W)bp*A$s3&Od+kbDpx2JBrAfVPM|F%^J47=Q&9CN55*z`?}U$d?W-*XCUdMuNVNhI8E17IA246!QjltlyLySNsSA&q5eZK zjfNF0OcDUNy|DNK0PY4FfK_lKe{wH8sezl7G>k_Q03Z!0BmwmZNkA>!gF&OvXjzbp z_RoG3uuQ!cyWESrfAb1NTok9DJma;`*Bt?c_i9`~GL1DQ6%g2jEWJJaIqd}uYMJB~# zfhL9puv6s*3!WXWShTp%w+}a7YsuT)^)ZrnZ5bP0*tN0lenv{=mvtyxCJ}ntXFs?$ z|9;^I4fVdbOQeGpw8-GjF%#;~s+-W+lSO)Fhb_8r?;2;lT#5b3>4r0Wqt{Z-bWZCV zlVgsU@~>^YGzv9{#bVGXQAAo4<1$_zeiuP7DAXV_9&Q+gRm3XfT$|{gy4S9n!v3;T z>zeTq*DeRwk#fZN0EB}^qU?@diZ!^~n_>-uLRo9kKkwsm<)$v(KliNK=dz z4Un!eDF&uFC8=H~Poa@9UM<;R2!(YDNt{dPWr-j{O?=;|NE`q08M-y02-!T0-48SGdUC% zf)FV*5&=P|Y$lUTViJf1CXvXYa~U)Q;gNYP2AfBx5P1lZNkiyNCWS+xQmJbIApB6J z*TPdo0idDIBqKyBi%I12sB9XWh;YaVnZ~7XsT3xaL82pzA*vHPykI!T4El=zIP1#A z$q6rTl31aW90eRqEd6}^EV!ZJ>b5~_dEnq;vSi5;Lyn)1ADbH*ZpaP}91A_@@Lo0n z!7OHgI{yR~X20N3%bl#CM_p0m7VZN*EdN=80X!Ny)dDSnQ)PbZR8dI);7yaE|Ap=p z1>LFY&_s0AYUXXGbIQ0zWG`bV4W?!WcveZkCXj`CdE(bwpL*ij{_Y zd@CgAnh`32KoEFl=$c7{5nulkLr6erj=XS`2*4zuqydtE5=SSXP@rkbGuhC_1GzOh z^A66*-XO6g?RxgUPPyA#JWzP`o2bosvyqcdA1yBXfqA={)@wGb5;Xo}7_`dwl=sQb~p=H*Th<+8L!!1?M_-AB4v(joR*( ziOjQ+#hHK3nWS$4nEilDM3-OGkCk@DYt1 zHp2Wa_9XvV?7=k7p}5|$JI#BW)1;zuY3nhQJ1&SC3{6^CWkhksk9YW1|1ePcH!^7l zXUNNm_cmB&Iye?~KRJT!iH^qQOi=zZYf|C`gVK9f2fEAE=HECKn7K6kI?+J@{|4xwE z`u7GUub0f+y=#8cB)1EuS{(+u30Bjhoi|O~_H@OJ1GG19??*3GY&_ID>Q>MpOC`FI z?c--w)AUQJPF2QpL_Zp~UY=(gz|>H_hdmrMb+Yja|Gc)NqZM8~TwPvD4`|vLux5}` zx(azSN6&a?VgPi&Tz6i>j3AngWcCC*!&pHrIO)wT^KclcV$m2G72_2N^nyt z5!eW0Cv*_Qv9sI>&h6&M&ff+taL?cQl-~yZ+o1os2K^Ngkx67a6X7z*WHOsZXS0Y@ z3KyZ!ITS9PK_;`v96FiDpi+q}4w1@X5h*ktok1cq$z&3nh7hO(J|g;&qlJj*hyUQC zB!o_4aS;lYfsl!0DvQ7*&?r*ibD$Veyg zA3$0*M1B%XKuE$ISb($;5|J^K1iSqb*drkX0ix3%lFg9!wIQlI+c~K_I+>{p1f&in zq;6qG_)CX;^P>#QVgG4%a7UV>Yek?=%u+emHSfAV-+%dR!`Y02_Y2KNht$b|ULEn0 zd32B1V{!<*wMR%?dpV_BZlm-YdQ?(0ohKlx6y* zO)QIgv{kJ+mRAsAnGtsF(BKf9Xf4qI#IxXCFM-SU}RM^DAH?q$^bNfOJCD$cV@w=rLqeJwM#rPkj0sQLB-<=Bf$ zGVjlLep~jb{)+8yEkdfMNBZBfvn`n5bx|sz-}*p7z~-AQNArkHpLXl3AC|_h=M3?k|;_6bGxl-6SJAP+YFki7D zLMuYd;iao#ryvZ3wuiEZluQ^pOlSb_ng{L{ zt2*rMT)hvMSCojT8@k;YoY}KS|6yUq;p>Jor##5}5S*g-1(`k}@${vWF`LCEA6?}i zN$LPDj>p`xo|jg4J$WfT(D3PUsZ3}*9_wATHOr6~ky^E5{@r)#cWJK?N}*zbD+l!`cGUs8)9$sN)`1JI=p@G1E?>7UXQ$)KD=F=?W%_+@UEJxR zG7o`#m0eifK^orS{~ZRpH0q1?Ft8`+V5P7R zy8jP6-B)bRrXxfOkHKS8DLf93&7iPIY$lz}rqQW17K2Hl(^wQDjmDsn7!(?VKqFI0 zJT{#`;vg(4k-}u~vH6c;H6NS*C`JpgIh#jeaS$qzMWG@@9+}2u(J2U#O(e0|JcLSx z*!*8WUOz+T=|ZwoR7iH>fs=_@sNd4yAf_a+GjU=Ehlhu8m;qcV;9z1CY{}$sq9Naj z1-3zK!%2|!v+|Y18o*$bT&Q&*y2=@&R^$U+yH~2No&dHp~FDxmw#*M`6 zIEdK;bbnY|f;8w40Q+Q{U<3ZB3?Qg57%?h?;ZYgb5WnL^uR~t60!ct07NB($_zndi z@hiUt$HEd5PF_qXHG(`M3vscSy!cn)5ym3QaHF`q>fq)nZfVA$fN|Mi& zG7ttLBugPzN+S?Sgdqg~&lu%ju`lNrvvBWv-N+wRt}Ew!Twy!^mF7zM{T1pKs40o> zT9Ryc>%9Jus4{y`ab3u^t3*_h$TYFpo!z|-MsA4a%Yrek{!J^yzH})@tYFNIdGVQY zB7AoK`ULssC#L6PR`zC}TQho5T%*LL6Jr!aDqmkZfK8uby^JW;1$dg**82rg*U2iM ztT{GrVKKcIz3z5RgSA+r__Q|9W!IMV6;5)>-Nf>nt1ZGDYZ}e|k_+Yi0^6c6aUPI;X&e zyUtI3IlthPxAm9XmsK!R@olz*1%B4YpV|n(J}l+^p>zl9mLqF>UrTw$JCej?d~{E| z`EXXmEJ(dP{jqf8cS_2Ks@v;4qwjs*>gI!CzFR&;ln`OCS3T8%yQ=u({>(EEUl~=` zxp!8DuL~=tn?Dwb`Gk%*)xWRk!I2LS8s%>|$t+)EeP?U$NyAC91!;vkD?YdGc7H|N zUGV%#!0{xdT_%qvI7Dxx-1o+|tyo#G18qN8nYxX8pE;We} zZ?25$gNzO($r*mZo$Xb<9hg&Mx|E%{7`aA+(F31JX;G)QnEbOx8or7)=^E|ErNa5y9; zo5>(B=v)qykJEnSU5Bg6XoO!k{^c+YG1njCeGr_D{uLSo!b-FdI|$j*sBa3;bL>=r zgNaL!-%@UPu(~ss?Hd#fCpB@y)SV2?3^iai8p4~1K=rRE$1gbOEBYD-QJQcU=g^3- za4tuEHaC1paH#(;Ri{@g4bFhDY&D@SWF#!ZLs&Ld^{24x`|7lsUtQFoY1n1Z?7w?>hVX-eimdZ zRu-t^8TZk{;JEwMx!wi2#Qn@wCxWDt?;_}}pC0(l+pEm*T*QgKf^s`Fl`xaO>@N21 zEZtUh?RZ{h3~5#0{kX!%)XGwO^!ht@DE2h<*tLwkx% zs|ct|?TxYqN}g(`=G^fbljqkcM$)aElkqvv`G#}y9IO1#wtoV?zJe`WF2StK=$wJPdt~tJ*4go+ zrh8yC_sE^&&6k~d19Q1pU*BMh(o=@>nHe>aI=glli0;4M&bV7pw|j?#4w|A@WSa5v zb8Dtc${6eWC&@j_Z!>m0qQ9H_(P1(KU(j0&@r2NW41urT#{H+x`j?!~Z{z-L-2XM> z{tCG$Yzm!BrE@409)->&GiY2InZ%$IIYbr(K?n$o${|oGBpR8?=Fv$^8i&jz5jiXx zmCh!U5jvL-xqjqhhas0J0!!k2*!A;R3`@~}5z-+P`#Cb;QAb^>!yT_aG*2qBNG2_Y^<1xkF`_IPi%3+(IhBqB;QMM<;_z*O|9~~Zh9ot*d6ci7;JnIc1UZA z0XR=_3CG($w4FaTZWFa-?xs;)6Jy8OE1kLCZZWa?yqULYzNKaN_LuWkWzA8W=X_vV ze>mHyXbu9TWuS+Uaaco+KJXP=fodtJQsEHi_hq1*XJdwO0)03VwK(Z zb}@Xt;EFB|tIaqyYEu4tyRGBIrb{{Ybi6T2kp7BQzd}=|==1IeC(W#KUh(YV&I`NV zAH(o&`~jN&fma-XRVCrp3}G(!`gM! zqvxeWZZBTnvOicYVEWLHaO%G-sKpPae3_{qV=4bMsg)=ic3ID52C`nW1)^TgA^IX>DNo-GaIB@BI4 zrX(C~U+I%nyKQcGQR(&-s|Vwv#w>`QxzKQv=@C1c{^aXdS=UB+ex!O-KGoJn6*r6( z%UlAcSJ&TbH>vGCJ^g0V{ouHKgD0ivk3Cy=lu#aD@+n+3Gha7LD|K*zj{mblhc2;B zU|8$6>V~6P#_MjI2b~-0P^T^CC`-F3qg_w78Hc2!dBNzZC(IPt!2d10Z% z(@eWdP@{r3OA z{r_+O|J(onSN#9ibdF17kk||sLgaDiOeTTEB@);q0+C2(ve_(zP9QL-WD<);X0YiD zI)h4P!O0FBGL=o@kl8E_k)O`}2$u|}bLt3z$Dwja2#?Jqv6&PClTKi<*i;zjsP9>94c73--NpVK!$<>4Vvv;JH}| zek!LaNaenJ#OvqJ&5j?Mb88@&kSv(xU_<&Yf3rX%3Fzra0;)oozlpfGo_X(;OQBrK zmA+SC6*}@E(0}_ARyHJlQbs~x9!7-EdBKSb@C!xw^*=F$pFFbLkoV~Hno|;e5^)-L z-<~@c)aaXu2}9b-G#L zl*2W-3U1V>T^Nf_8To+F#v>_td;Lo+Zu``04PwUSG)?=JI)CyAe1E)dM(*dm6%UV4 z&2GxF{aAWuW?dP1w=li{;i3uP@R|1k)8%H~F<@L0$8QbmPNA+#(K+3cvVKld9{Y0^ zv5~h~`rXYU{Dy{rf?of)J!pi%^SH=ae=2KE{egS7*&SEw@7TsEp-x>(-Y|Pz%A^B3 z^4C<{0cSrsH|==gvFx~x5(J1)WrxUIsK!G8@wbA74o`dMKkaEl`mJF9s)BuuKqLZ_ zL#2}GJURg(6G(J6jYQ{>7+fZqL_`QA5{W_Ll9&WKn~e~O3@Vq$ps|TeHiOHf(ntgj z!jC{dvYZhSh(e)Is4O;*NP&l?kSJ^tlZ@~<6ef#Ip%H)n%!>`_UwY=H;a6wYDFX)+ zr*LK{&yO3x`KG`tm}EB@5{h4U;H%kJM)B{PWheQs&$2TZ9@f7!&F&ej?=~O_Xkl3T z!8E%K-|~pRIL%HQ(GqZo*!p zhYerQMZq4sXFS>!-IRS2!*o@?WOL#{r3uAwwZ+H1emfi2jO~|K&n&iGLez8ZFKu7f zpxGN*ufyEh`N2K0J!nkn>dEzq9{0lg{Jkqy?~`#{ZSB&1Dq>tq+;it6vp%_m&O?v+ zq_o(rO;uMcykggka{+XEk2;>vn9D}4Nx+KII|tXuWAQKMQKzg%ipOMCZ~ zRr>=?_Vej?%Or_vd5@5|%dx&WtOI**7l?W2jAYd$_|J@^fUH}uwgVub6#Mb%`?%VJ;)CYnX&vb=IBs(4OXxMkY4rGrEn&UB8;Wk+R;y_5&0Jo! zyy%^n!HF;DD|63RZxxw&=C!geI_<1;6kcO-&7Iisj}!~@nI_fZK=aGhm>YPGmBbX& z_>Zy6h&|gX=cmT%cc!_8aXwSSy|nlC@I(yb7^Cy``{t}oP4eshv*~xg&3|Z8^}o|$ z{WkyK=Ko(a|F4ja$mSB*EQG~laELqxmw*r%3=)sUB@!qE3Xx4>5jh-$&17-71U8k< zrH}{=7M;W(P{i^ikyA>EI>?l7biPRslCSPrR!KLrSXJw>lv#{TEeAPZh>2wy0R zi#sy#&65mL5MwDa1wRIZssaE<^W@$~bq*z%|r2#+=VBZmvrWmPgcsWW`E|r`;(KBRFFM0nFo9m>krOB6p zV_c^BXVg>T+OpXLVM$i(Z+ws!YOS|IFjvr}|5r-FsaZ+*{*# zJ}v941=%m5jW%YhYukwf3Qc{sGun7DkZeZ!gw@q+`X;^*zH;~Ykx zeej0TV{=@q$%(#g`NhyYR)Xq|sqFN~M=zAM@Z`jrN{6}X`&^QZdOF8SzU{2Kg3)Vo z3)o*t#LdiaYaZ}4c)G-Uriap+(mgABc1<>0lC5x(v}{W@!RM~Wv}Nqc++x%5vSP(L z&+a`NHAP&qb~Qt~;?CSpuWIzhY_r{8|4#PqgtodhXC6hF98!7EIk0?SmT}y11tV$O zSMN=ZuRoL)tzrLaV5OP1>)f;RuCF~evAaQG+8h7yfr$S3gFR;_G`fCaYkZJ;M`G8u zIb_Dax+Y{YqZZxEYXuw?6|#Edcb+5 zxo76$sfPMTqf9$^UP~?Yx@VTHzhu}De!~IRRT@9$zE@mW?=#Ddr{f~#5Hu#^RaQ({ zk2$PKa@;hP5m?&z`uUb?D{;9Kw^ra{yjLb#?3q6GMIZa_f&g6J(r}l32@h{^*J{KY zQV!Jbe(>_t>&lcvw{)!v%#`znPT`ZBiz)LXxM>q|V)kyTaCR)6XdPwGx|J_)XgIxVfBW3(wVo-8c8l~diBA6U zlIF|g?cVl2y6UHSn0MTR(^56QA)wGqTbdWSUpzoctZc@X^)|&fV=pvE06i!BwN(uc z2dq3)ZK}52I%USFbe*Z6vvk~1uk2CdCP~$=d^UY=dbIS?Qa=kxKg!lO!GoD`4kmdI zK3iPe@pe(0_x9xjhs$=JQR{nhUiwBe^5W^oUhG<0?i%FN&D#x2#cG!sUH!OCZmZIQ zNv`RJuF40a{cAk2?)KB4t}n?&&(S*l9%ZB>l4mYQX`G1APZtAsX=x-yPrfA8&0Gc9+*!_dgS)Et(BcJ*D(Y5T)l z?L<7STb~%T%hf3NS0!tPgfBXzcroYT)oo(Qxpjq)@}=^6BR<@GE!D44Su(~jB)I%U z3@Ya8+FkoDhfE6H7PCb&hCQNb;tir7_der26MC7qcO5dgN z9MhYQ&pm6XVdsPH&Lb*vRxw|nI{O6gmsM{|KfCCz?agEOeLL^I@?XC9R6~`WtASZU zcevw*h0J5q*QVF)a^IzTa_he4M_tVeYVWi!?2}Qy&?Gl1ELh{QF4w1I=PA9U#LMLisvp|drA14TWWgpsy(LJ$qso!w?Au3j zb#7X9`OCQ{q`8Gnxf+eJt=y+tzA5;ZbEXp`sLWHFT$H-y9@cn82fdm*tGm;2#r?ML zZZQ9mr9;vVs2AKKdQpHS?bxdO#6@b z9+!@fh+3kT7aM^)9JZ@y!Y8A^;4B#t-DQD23ntBB+)Fa*w=HVPIq0rhaO`~vg*2;P z!y77EMmTF9mqcykRdy!iAw)a*q%q$c7*$=GR4)iH*c#)Cctu@i+ z!Xp!Q-X3>bE8AHm&v=M;irw|incYuAnmrC;B4Sc3Z#Xwz^t4$eizh7Atn<%_vX8oZ zU_yv?>sl>-&U9p8m}nLLo*DmHbE#zme{5r2GE_(&fMO zmPkT)bTXOB<*~_J0>b3bX>*f!Cyj^8v0qB zKd>01hFA>9Sx7<70yq4w@1JlM3Pa=gp0LQn%GMB{YwQ)>byVk6{VaSh4PTv&%i4G2 z$-b$LGmL3kmD=XSzy;SPF6*|<&hp7|dbO4ot7Rz>c4c=AiKjH9^TfRN*@wq+Dh`CL zvsRKky!jF{&h7SFeLbm=HCdRQ8|d!-Hcq6}3FS6@^JmH8G*yg?h^x<)$KI=3U}L)F z?R#FN_1KsVsAI}29JJ2N>1QT;U746{>QL2ok}xfF(5>b3O4s)jyY$V)w?@Y*<-YrT zNRAmbiX^szbv)TDO);u&yVo0?mrYm6+9IdlCCKZW2kZ8)jC%O~l6J1gwg(lXT@M^m zI5AD%KS|F0ONsgTl(1~SfkV{P{`;jnH>ypJtG-mao!PvCavR`~xjKu9(?{*SUuJY+ z9clj{cS#LsUF{xradW|<(!8rp>r*F{<1V15s!QGQyxe&sPo^=P_#QElWGF}%dM*ro zv>v}@@w*b0eNW_EC|}l}Skf!6@3yM)P_4{niu3_W;ksJUxP7Z%%S|5}v5S3MHF9IC z+(Z5AXm2eKMWY~3S%)nzCf%@9porxj!S5JzY4V4T^ABGcGxs=(e)Q&;ZpnK1Sgy~T zbM0^qZeL!jsMbU#9xZ;-@WzU^q6;ylvqfSfpE}7uxf`(J!@WCUNp%SlFSar$mLAn& zjs}s6X3NtjYMxG*Wp~5tO4b%sS$@>M{o53HlcVK24k8?Ny?eQ&2X~tGzJ0WHpRV$Z ziNzK=*Yvetw$GKyOI);nwpYgf`?FZZuNB!MhYeF`5=>$JbCme6#I)v)mKTs}hOXm8f z2j07)XWTviQJ1~wsH)51^R~p9WY52@bueM{=sTaup~iEQdp|!>nc;Ks#+eTvxdWqP zJn* rN{z&YYQhZ~C=t{n8l`N!vS_-VB1SV_c}Ky=?gD+?M6|Risn%r`H(xuWF0l zpqq52zT-;T%}}j4jjoFgD`)wh_L{=u8s{E0FO9C>lB#lIr=Azh^M$E|)qBjki?_Bf zy)b_H8J}kjU#7(F$j>RYA2ogA*@q!hQ3++b85)b{$Q?S`5vV=kOH1LU(c4p*M-Fe} zU62e&wLhqZ&Komn|2o#1vnT96-7FyK?QT13UMSu3I8RAj=J7bT&6M=q4-dB{uXZ>(Vn=iQ#?*xuUl0o3Oz-6!J?g;C8DMS{54dJD&6y&WqC08R zr6snXpItgKm15!v`HC@+uNaLap!$V;g%Voy{HC@V%kR?JU*a16imy;3j7L=Xb!y2U zde6TkD>gMI4PMd|XDzSx#H_6tLpNaV%7`y1p-OK|mZ0-j&ayCV`zY^ws1Rup-E#`B zUUJ(CJu0vD>Lb#9w*>b@xm}CPj|7$Xj4HG5TddE@nX@yV+a+W5;lesBam}n}j;nQ6 zAG^Fbq|V4|`};QQ=T`>DZ9-{E80a|5pILQ2OXk6`J!Y|sgAOHja?jfMVXse?a=G-@ zs^^yJzV1oY%hCoa=Y_6xH1*we?!-o~>^m>dn=G@F?~Oq>n@7V($i|uIn?=>O>^dqM zo~v^AEN$!jE&*BLh|Kx6o{KFU!A+QZZSDBv-cv!C_x8(b)|13Zn`*v&iQa zPhO<9PPI9Ia{&U^Yr@obMw|XV<5^FR8ni__jINh2QQbm|UAMx%86htTWrQ zR+5SvW6m%wlqDp@)#n61eVi{td&Z-;nqN<$U0UZg_n<@IsFQE)4y8PA%pP^pf1ezBZAMw^ zq?p!2vE{*=XB{{xH&t_?bM43Q@Y1FeCkiJ-6n5gw4r|wV9VEJ_6r8wa$eeUy08@N| zt`@w&C#%Wr&&Z44X7k%@e!}_vZ#NsrWc-G}zaj8%2>crY|KlMrpU9w+SZpqtM?|PB z0)tIv5qV@fl}Du`G%9?qAE6LfB!o(%vDq{ZjmPCu7!)#(&Lq;wWCokYCGjV8{0MeI zBIAc}3%(CihCoAz2-V!0L9{ZrB$4^##t&ifQnBx*X8bG6hV;MAY{*!c%`qU*tu1L} zsuhJ!AP@h_&S;n|$RY`-&%$hBxp$TI4L7Faclhyd$rea8eXeL$fnD?3OhwVi7pRW^LjhG<)WFg_sgR6+UIMO^)V3-P->!ml$s-Y;hb7g zBYNY_lKi4=Ulh0#=juK6ctQ5MFe{F@k}EOSZn|vy$+&CS6#aQ2QRLPQPd(qW*YSwtPPw^ z`>J!a?utxlDB5=Y%%pU*D7ro3<-2JsS$EzYxpX5fvHX+ODzn)S{hRj47Kb<$$6miv z8e)C?f?VDD^zLQbc9yR=GQ&S~(q+pDA%{PBPu9xljGmFHYV@$g{GHWQ@1^28Oq(|` zzmh3blt<^zeZ0sZ>srSB9rGV7R!LdN_~v!%znUq`SuS=OIhL&CrM+Gw%=ppR%*e8- zy7UQ_ffvgT^?mMdHUGS?uo#^wTE1%fG6}EtD~Y$xWtdEQFEM2WyQ4bvbckC(MdsKRCX?fo#uSjE0W zWRB;Sxf^aI&Qg4`{~oqNW~SH<-IYr=FGyRekS^j-Q`Bows9R!g;Vh}1?1bYy5;=G>nDZ0oeC<2WY7u;-Igi;`KD?^w?g!|PVR z^)Fhkm{j~Fx=?*j++`1y^JR=kktbe6+IS_g5bb07(^z4 z!$gP_5{b+v^P}&NT-l#TUz!!g+QOPlwJ@hJs00fCDVaZnng6TEEAu~$ykt7vnqo$` zBAA(5{5!AQ*#V7MAuNDp*_ESW?*B$jy7VElEYg%r$C)zJ! zb>QkMZdvK1pjm73ALhx$p~|0LD0))%Zdu?5k)v_m{$dhW2IL=LH^rUbaP9Sq05%DG zB)b|Ny7azCcc83ftE_#0;C|IhFZwv1V_dEiSw|Z7n{9k1$8m~XcxAWgy`TzfYCy#s zo0Z!&P8_rS;FxX@Q>~iYZ(yD@P&Zz^!XcxIcsAW|#u<6hDwo0I8}4ad&V4mM*XglxU*iT(VmyK8Q`wF(@9Jo819jvs`uVg^Cxr~=6t!@bhvx* z!xaPXri2{bHKWg{v5^1s9Y333^oPj%+hl&54C;Tq$$X8xEFy)%p|cSxo57$^X36eg8IAd%?^lSW1eOgfuDWpOzOoy#RKDKr+9PGpmrG!juz!2gje`}4?4B3fFT zQ!UM`=vLMU1tGzrK0oq~3^NyG1vxJYNCSIfEC4uhRaNmg__MIWAMzebf>8$WH_-+M z2Zt*BxQA7{{C@PPf-DTkpJn(jCcvQqc=}6qehC6%NaFty;Lpt>dDt7TFV~%zYJ6uy zzW;@HkH|;uOJ1JcCwEz&V*l#0^r6hbX#pRUd<$mP$w_Hic~?&h=bC=%u}&xSVIIWYfN!-LmSD=l_3s3dR9?cHuWZc@jR_coD-oN~wc zJ~q5pr)H~cCeb-97n2fyVM`9Ullvm=#bGJbA=!%loEtUCwruT)o3Ux=JG4v7c~kS* z(lcz5?;o%6@;GPdoRd^j&UzGDT=;N%R-NNRwfThOeySBN`HpnTF1s1)0&v9=JC0qX@3~dI>-nkpg1DoW6&?kd zmBI84iG((v`<6L(NlNmPGoO*Ncd<3kt<8_=nNOQVYP;GxRc4y$TqJT~OMyNoZ`F$0 zG7HjuY^(8I6-JW>Xy1Y2-CKj~sC~BE{L)StPH4Q-1SyKQdjz{bI`~p{{%m#QjuhS* zk?PwX)5ZrE-cOK-PItV!u_3OwGQrEOC3gH()qqE*!yA(ON8j3HHXmJpA_gPw^u z6Z;r<9h*feAE;mZXs~^6#GU|V{mtvV1xq;@Yu-6uuGxx+-yOB^$O4IOuW1@2@#ig|gnDL<`jRUgk%B1YwEmg)U6$Ef%hG#~HBaW{Pjw-Beaig#^enw>(dzr0$MpEsg-cRZCpo!0Ydq4q{Gvtg zT*5|cv-f)&-o6?y-YKm+E@Dgnmqx2=g9UcpADnqz<(;M(17PjDwnV!?n$73(*!HF= z4?eH|WSirx)IRw|%9zv6A6`*a?LJIcdU2zjYx}2Gq>NV}m+e{V+k$Cn&v=TY#NEG| zNa#IhME!Wfp|j~|oQib)5~B~&yUI@}k~Z#KonA(ZZk-@F@Cgl&#%%I2QOH?k$ z&uZ%Wu*Azpdxw}@;}+4aCb!46?4IqpBJV{;-wnBglSD1>V+Ti{n<*#K`XEk{7eD>Y z<@70e3a3b0YZF&J7<*~bN|DfQV#>Rp!t(x7NZ3Up31}}NVK-lUL%dsW=9TYq(qBy* zh*X3~BonAaggpGJli|k^EJr-yKHH8UhseNMznCQ6EHEsb8_Hn@4(%WziMDkfdTS;| za-@s>%lzUPE~>dz34VG8z%2E3QEbHuxrePBd_J0JfchjqqFU@DA$!I$8J7ay)J=5H;SaJoh5=QPchP~yf!3R26>wZNMVG5|bz143wPE*K zE-@mFKZdM!f5HN~hV>@urmqIv_7{0ikFwHKmy_W6sob^>sF}Ph#jSSBJnAcCldNT> zg62wY|JqAkTtR*jzaEKS^X)7EQBy<*{>X|p7XCE(4}SV^cpGNKbO8%XR(jurae;9x zzsoOAHSEiH#=ZI1sR;l1a#{Ezj;pXRFn^~`{P_bRFL1}i)q5|w9@d|}cFogUa>2nb zH}BR_dr`T-qB%;*EYnD)zvonQL&AOOHp8uAaZ~8~S z_Q`+n$sgZ&>5&gLidI3WB|6K@XZZ3ne5pC~Gkp11%aQ5mcF?x4WTc=G5fOsSBqjW@axe%$_|<7j(L+I+BO&yL1D&C9H~1 z$tbT}9ukX_LWrRU9}+@zyWR0_60e2r;0@4#gb@F`Itu#oE3drr%j)-c?8o!P$=3?p zZ}%Gd_JsJD5J!ZltO+63g%F!Uh)4*L2_bqyh;1Rnju7GlLWq}y5ML~)qWBUa#D|3t zUn+$7G9kp53n9Kj2=SFdh>r*%J}QLxyF!SD5Mn_HaYmq@mn)OXoHV2UKdJtoLw?J5 z;On#yhXD6G)&K7j;?PTk;*<4+mEjY@pTwquUGB7LH++(>i;*vruEtC zkGJ5D&ryFI6JqG4st`km->ROx4Gj(BYXo0!$JZFXhQ!N9MFkgcwSqOj*UqMeI4Y*_ z^$5ORg|85bsPp^Pc=;&4UWcz)A@nSn&ndj9mAp8L7boyFT=Mpp|Hqz9n&rJr z=uqV^XEq;GvsnwGX0p@8%@+TCOf2XqjXK?0GwyVHQJ956`mmxFx<6eA`u{nxIQb?a zzOy3UBo-%M4^n+y37vrN9uNWvX2fCfGH7;4JdUr|;_G41*F*R^D8$hRy1mtQ*d&sF zTnN$HXm-cbAlV9%@gycBod7KVg;|t7?-WA3Q!GxRqXR-zD&plscwZ4>=;}TpjvlEF zpS^tP{FNKeE-suMp|&3tFCRVJY==RVJ=^h{uPb!LJw2NS83qgyc1$5)pAh1>`n_KW z@iz7QfWQ#=bI>XOfb$y|(Cr)&0^CiX;R>EFPF95Y5F`!Xno==bf)bVGoUVrN1^{Y3p z9k1W6*A0x1!_hi(&EP)i&XFOy@2D!!Vg zkVPt*1HS|C=GuB)0sbxr@Qdm<_~%9S8?*C;>h~8{gm{-&oZR=E7<#bss2Hm3e^d;K zS3N3*9(e>`kK!32?J>N-3?96l)+R3=cvKucxaGIv^rEVN$ku<;fJXM^8kwO+9;8NQ z)?XBhlZT!YAKEYe;E$@}(X($A^^d+)9C%4o4!$HRXnS8CtbG7$KU(Zoo)d@U6(MLC z`!SZ+0qzH$6NkRXbI5uA*gibx8K}?<98_aHjA06mN+Japl?Ns-)~0Hv=5s4g zo0^9RL8!40gMM)4Vr}NciTba^1t&CfQlP`Rb{nNo*z5m4rKyO{=% zYr0n`ANZhG>^AUuK`A6dQqhZ4JXhH#AIa^=wlG;%8H+(H&L(b;cQ*Z++MMZ?=#2_U{QpLl+q|baOzfbPQZ-iJ_nT|$ zTKUuZ3jW8ceE=)gLF53$N(mIu#^~s)-}9ci{J&RWUl(NKVK=L-h3zaz^t$jg76FC7 zXVh=}7pdRw;x>9%h^O~2PJXs{`C~$?(pIoZ-!1z7rwv zq~fQA5T7N4_*ojV5T7lCcr*5?f&&fyjSxZ#A$~y!@$*86Ulc<8TOq{16GHrw5aQnp zA%0m1@qY**{!byquLvQ2P6+X9LWuthJI;y_AFT-S8$yWR6heG;MTq|(g!rTo;_E6x z{Jn}0Utba8?^lHQhKdm1SP|k)LWqAQg!rb45Fe`u@y!(>zNI3>w^oGshZP~dts=y? zSA_VE3TfElyDF?be|JTQ@2Lp!y%iz;r-~5&xFW>&RfPEdiVz>K2=N0IAwE$N;vZFn z_@Rmr|D+pb(#YP>BDfBE*kZg!o@8Lj2r=Li|KU zh@Y$o@h>Vu{QQGL{8UAVUwlxApRTYH^RI;v|CnG4#s&@n?dsZG7DZ6g&9!0em63 z1UP?4AfN>?D+p*oHmo5iHbdfz@b$Ox^>^^~At8po!1B#QLJU1XD&P^keKi_?3>YJe zz!O3YwMJFDmx1Oh__~U(<3b!g7)IS*Mv|ij#r7@uqV4-4etGypxG5H3A;h%<;wWq> zCTG_(`xhsfhnSz3x0ug9!&QI1TtzeeY2>PXs`vvH>r zM461&WVR8=q}LAaYZ2?SLcoxj%#0^-FAJk}`d_QTFVO|>LO^*CPeR#N`qgV-=f|Rr zP4c0N5HFF|aHJwe4lhp1S6)V}>gOJ;h>?dEC*S(Y%R@rqi#Q)jGqha4)k;!rv3UnC zxwJvhzoFae-=Co0YcM~{!EJ82el#?xjJb~E|BOnQ;zq6<;$X1C>M!Mwb)CdAQ4_%Str`akSI z1|@F->Y)MS?d4!pmx8RUEC{jRnrW7&`u~T=aosFZlaDARY z&b_$Mi<%1P*QgguLB@TakG8(CA8^vP4eU>p!|pNe&iOm?>_*Vslo#SeGK%C9;g2Af zbL;JR)o;u7AiET$+0AZiURIqyfXvrxfVqs{ZgWE)9{?MsS^nXd(lnF3Z}d}waZ&tx!HP6mr*B%mKU)BniAVs7e7fXz?+SUJ3V zocjAj>+1j|5m0U-U@!DxVbN9x_;2yS{|oFZs6c?i`fvmi>s847cjOR60Zb6DdJvR0 zo^`rw>3GxcrX4@3b^Ye1zaFHp9jzu|Ydz@3NtQwg!!qz~st*`NKBj(ShyJbVH>?BS ztbW5H0ZEU~-`$70i<7W#JR$_GIIzCFR*1^$g{Zti2zU=GXcxO=vRDE)xEemOYe%R~i0>A*>ZcFTqRw zHj>sK`!oT0FTlMKz`bcV;10c72=-xp>t6$WZ_+-DT|wNZLHy=V6Nrb{P05S&9_CmA zjc?oy#-UHB6?t(IWj_n%^k$G`05T(&+5Q7U9G%$6vhLhCTAmtfh3g^u8EeL!aec)nFF3fL z?Be8DGig5{L|s(A>iggRC(r!n5B}1}hd$@qkNwV1yz^fLfBLR}_d_R_e^h?gjW7Sl z<4a%jr$6xF1GC>gdgGaY{*%A+1vfvLec*GB|MsK*EcyH&{`H5~{^Et-9e&sH*%$sG z{L%0F58wIC$1X0%Uo`R!|K`$ny!C&6^UCKu@upAw!r?RDaqDXy9-Cd*_Ybn>cR%-S zfA&2;^9!GU@HOxHz<2)WfBm83?>=|?&p!O$e&FBUe%-&H`GIeK@0Ik6-t^>=*Z$G3 zeEgC2^lNW?-5)>wv#%NYu3vrQ7hJ1OedyIc^NGbT{(rvdcmK)yYY$BR+!y}V8@~1H z-_rflZ~LbI^!soArlsGw^k07dH!dt){L?4rzxHd+9RK3>tAFqJe(9h6+V9NVUjO=! z|4RJitEwLwUXOl%=I^}wr-p~VrTMF0@wflwe?9re%m4734je(YkSpE|`G&9g?ca=k z`;kBUvmbu!_a1otSI!>9i;V*(UjNBI`QW$wz*~O*FE+mS*Ux?3N55?Th@QkW$e_L& z7d&JJKKTE0SRRsc3D-B}HHA!klmb+W&Qf-yYfCURPkiwIC&c39TS)f3PKhoht}2Jc z%LrN_G4+rT6^OZmLL7R}K8Q3iv>$?(otLkI^nvAyL=}R3NJSzFdIKJR7ILq?5x+hg zUvE|gj-nZl0&Ylz({ZrZ3UTz|cHpN$jTNLJM8HJ7=D8=&UL$(PN)dGYkZ2qq?LWl- zaGl|t*i-w2frjPiJ~Z^2W)O928}02*t-Fz|)>_T2_aDM@^82M>{I0Osj(aVT_I@Fb zzIid+OyVmy&%UFiz-dI_Jeqd0?ij!s>jbEVbwKY1f;1(^@QEABgSJ8d^Tg@jSk&}y zxI^`Cj8p%H0Z;#i2TlL}(tY?%eq~x{u)tt;QaH z?B%OB&t15@aQ%Gk(zV(`s|Cmj*>`PxpWFD`9?(8s{(P#9V?8vG5AXjI3$|dN(x(FX z0k`q$!5{pzHhwVQ_y<4L#^3Bt=mT!!Z-3zL{kYrur;76j-Nr{B`9r;9rq5j(e*`=4 zAdTCI+iB8{MXPfN*TV<@e;LOOeFzE>;)ot&aYkEgz10R+yjloE_8fwv7}9P20k{h0 zu=)w0 zSf}9v+AqW#RUaQZAjGWt{Ury4_}$;;G9Nx5#7(t?f9V0n9zI`oK#2Fj_lO|K1449x zE?D^ART2NMy7&l<8FaTUxBVmvqjl*mN43(=aD+! zN%0vGIjE=M8Q8rQ-4u95Gx9nsn~LC^(lmnLcF^o)f$FN^-MTf`^^-J^%bx!Ayriig z_U;id1D65I8=04PZUu_SFS*XthWa;_CiDcX zDpf^;#6@#ioMwqM+(f)fHNY-hST^G*3!*G-C{ER^=kOl&RdqzCsylz=@Lix(lID(# zqgs$8aiV15x}?9rA?L4Ozj|FVpOlgRog;^j<@z4jWpR#~po+6cGfMdBr<{2S<~WvT zF^I@GfpAtVMJ`^(*@XTOo;j1Oa{GGeEs<5xclE!|TG)vgX^Z+)xLyLDoz@Lpf-FA=#M=`!5 zhb0(t5M~Q&JdL4mSr6CMXrx9mwK<5*p~PxFr-Hi?GYS)%GnjG2Y;rzHARoA&@hpzp z<7+|I+>pI)JN8?RogkIHq}>>=RkjPtev^E%4z)l954GncGNYXHlR-`xVVSq-#Qw^Nm@S`YbLwd7rY#T;B z`}`VK&a=HVi#yy5q`C7@shm=39UE(aREt4%g0X8~`blO0msJ#Ak$UNfRkH zs&EmcfU+AlHyOs^Dji&S0`*6vYHKM=R#xU^u?s+5?1SOSHHoIsxSwPzcVy5`1FTkx zere=9y;TARtrDFwi5A+UB6X+Gog;_m62gJ38eGr_?dBv;2=Z3doz%M%mGnkDIYH~T zD+6y;^X*arkW8Mw?y)<`-AxYe?rBBuH0PN2WBG}XyFuj4ic*ybbfp|rmlm(dvvIH8 zl2MFxI7|E{wqxXe3tIB(l0<-c6tv}95_dF<$uvvCXnjsTr-yzuU5HwW!JZpaD;?GW z=p>RmqTi#kNxsTCJP(Ta=_Gh-Hm#DO!q-T z;i+KfX}{eIma;g39*&B7E4I+N*=?P@e)$3qHUBba>flB$HikVlMsGxhsZ2NG?PyHRZf;0GCl5te zkhffW6^>`dks2+E$j>|PspYyjM{L~bCUF<%(;8@Y)B#?Zh@2-4FPNBKTWk8QnbmrI za^~dJM7@5Z>HE`D{>0>jKRMYt70jNj*Vm@kR%e@Qr)DPC>XZJ-`YGR^Y0aECal)WE zXGw861^X8FZ(TzxJhY!lNo7`_e(PMg?lJE0$-hQK1e)Z%yYqVK!i{USRf-JqN?xDY z?4E}or{+hkTCdyEV9}-$?c_I>G*2-kNu$)Vr>zItyd$d)m+BfE2a^)JYd)+lk=9Ai z)bA_7wp`KnMa2gtW=>^bOdUyu4_ixAv;_=js@&KZt)*0^e|QNC@*L?AS*qHG;!5gT zlZM)O=iQh3 zl+2fzjJYgsChawOi!2Jd7k({Q`j8D8=pUzwAj_?2cZ<`aeXd>%NY?XmqZXT+UHt7# zpk5Ykc3TP+Il-=lqHb~E@}dj4jHf9{Eu?yO^kdh?Pwd#oQPx^c{5aq}F=PqDacx!@ zO1POhmAJO#ZJwF+lxs=Q$IJb~;>N|=nK&zdaV1u(To^}M4B(^5;9hyJhtR^$a9%TL z5b@qC=aos{K_X_M!`hwV^n!$;?Lp01+F^XDZHL)L+{{lJEI@1z{lVIYTP3-oF5Lh+Hzd-f2|nx{HWE) zKUZ#6>I}w59^iZ{E|jBX#MK<0_S^HcY&WO_?j;wR4U1dU>#W*lM@B|e!M^5z<6L|1 zc&l~rWBCwH>kt2u6^zq?C+Vt@jZTdJDZ%42P$mYVe$$FS=^j0aHGYwY#GzCp!}U1nf4q!WOh0I@ZG?t0mK}-waS`q1BSU z?1arEUOFe6e$q04Y=@iSnC_O~!ISYtKkE7Ixg|cmaV|_Z0fNLC3OZon%j*k^H9VJF zp)Ze*x59LjG=yxY8#E}6MACPyBe&@I`+PA_)dIMs}p$M`e z6vI|@C&}pkDYdg8Z&8UoahtL5m(;qfraf@IBa z2IJe|TByU8da_(NTjjd1C{XpfDvsJj~~|zZFcH5^}>& zMqba;`zB zrdASboRk)kyksx;{M$R}<{FenzX0#$U(ZQBJ5Z%?O29o6>I34A;V-l_Tk+9#nI} z7h7vc6M5s~S`&FhYa$Da$V}Gjx~j+9mf07L;7&SX=c*is_<&Zgi-=16LDivV{NQWy zyQv&svtl_Xbp^a+Wn1g2bNX*OS4eB3o<-E&>1LAkYg9cOcXyI-eIt{@%@H|Sug}yb z>ysyV8z(u?{axC1a+=*dsHcQVY6Q-x7Oapvv$-OzU@L3}HPGNF(<8To#Xp2qMd{go z)Jo^nD;zN7q0%Gm#DJT5xBaNQv!IRL3b`evj@>+#-+WS$La^#FV;y6Y6eIU8{-k3? z`(n`|K|LwMC$~sX?%Oa??E}u3N2%d^F_F?nlQ0gK9Icia_LPy|#&irEnkGRtE=|w( zJt!lJa_&0a3xe#tJs5n6JPSKWcu^Fp2iTmP*>EkscxSsgjdQ46l|Re@y8D8(MhU^}QUe#y-(wA<%cTQqH*4U!Be@#Bc_VH`?s zHIy;2VA?BXeR8UCE@d2J^3&o;f*^LP-iUIMrdiM;FDb&S%;zqRkiXL#kuOS*7T^1BpdmfK-S$T0+uoJ~ z;Fi>K&>giJiEEvM@j^QXY2eP>!mV*y)l6*DA z=P-1klbnyIuM`9qx=lIM%_X)Gt48FW8^@38zzrLq4xM52yNL5mAw;g|A}*{wZfnk_ z#&w&jHZAo7*+(04!bP?XSy_rZLAC*ehpF67;%HsM2rYNwUgFL{N^y@El5suoApnYy z&`)_1ufunZCe7J!_C<|i`$-#;)Oh?fOU2RJ)pm#vTV5dOtVF_hYB56y}eWmi| zUT7bJ#@U}0NYvpdco4!YbtRWG2YOY5R8WB@pw=@xXRj#UC(bLp;)fS3J5pJ&5RDMw z^&ZSnOFEH>!x@UdsD>@cc$Oyfi2+e@($(nv7LwU``N`KFVx6ra=N;A$RSJjvlB<&A zcza19qH5+R&KT5Ht`>Lp*c?+x7Xg<|E~1YlX0q z^wDTPMY8d4%WpR(T7zeTD7JqtF2_FECJ@gauJ;n3Ldy_9w$_W9_`{Vov3#E5or{aj zy~qtB4I7hKGU@?IZZHBB|Ex9!HssK?zm$~ITO4YD_ZDQHSxndEUQoc{x<mvTB+gQ}Mo9sZ`Owrhw)UXI^FyMykS=t9pnWW(5ViTHHsO5G+3RskP(WNRkI9jd<>&^T0^SbWZMlk2PZhtu8nol>QJ&*4 zl~J5@{Pvg%FoR)mUim0zjb-q4j%AP)243%71EDzfRpgue-ar2+`6hAlyDu;snVj4P zU@t5_gW2#~_h>eB+k$zAWrUuaIj!9=wCXL&^_dD!?#)#A44=@Qljq_nlUdwrZZIO- zVH6y-0oN9;>w(|eF=7QF8_VMmE+n00&aDGXw$j9PZK>BupGJ`Jj+U*qNAAlF z0i~#UTR<(f>7_`4r3+wq=YrMVy3*|DY@KU3`pxe+2LG6r)x}C|EM^mUQ(+JdL4XZc zZ97-Df+PuBIJ#xXlJ-+0{ovr>1^T&~Z6G|8*E=~3f9$BFq%ET)JmK_9WZLT@dV54R z{RlJFOJRyn<#y0+lb`C6Y{7$?$t2))yQTc7L31OPHB^u-2M^?>4E&ZH)*h}TZH@)o zanc!U1>?9=Wc=LuGdC}eZDgJHF{)bQfYK3ksKr`4USCJ*NT?I!3`-j<{zkbs9$2Fj zbmC-(y`;+0rycw^+0UChlAt_s<=z&^Ro%!ry8T3Y=H?N+w67^j`CT8cqlV=Sqzn;Xs zF6LGvS9g44BMJN#x}K`*4qyk+qpmgKMB0gaa>K`gmRJcA5Iu~9IJ=a|u$9VTP$>0- zKaY+8*f^mhnY7bN$K*vokxIYaj>OioXqnmkoM$qy##r%ukEICW~0oUvHOj-l$z8y)b_|FCK zfnVw(UD7$eq0Ra;!tU0zW%PJ!BX-ybrEbNABJ7aOOPW6r)K6Xs+ z@YM0JF?lUc(+~rv*o$-yYvpP?7?tffTCc&KGb(Z9HH_9rL1sZa?jktTj)20F19h-Y zdR!lP21zI#p^zSx+{&Y}TkM;IwMS8rTfG`J16k8R$N0-nr5C3(H#;27z~i>h;4hTJ zVPu?9Np4}Zv>~xan@XV*MfA@Pi9DN6DeJ|aZU9kpZ1dwQ;=F18HVeA)QUUjD8)_PSq%BD zJrnPxYm|zRFB-FF{P-|^j?HpaabBc)sTD+7m|@M%V}RSIgYk5NY^)RYnqy4W0a;Os zHI{;?bta7b#AtT;7V-W(=bk7?7X}OOt^OOX4=z=r{PE^a^3EF}5K@yZLL&XW{S1+Tc_8hAWFk5 z+(H=98a7yDED3c|=03nt-mOoQ%1AEuMz5T%E{Dw^N&{7z*K9;foPF~8C~yAKupLA= zzL#!>-H~E@y1uJTFD*SOp9*&R!Av*s*zMl2Uk?BnB?eZ}yj6sXD$&c9)$TC#+9C%5 z4(JR;7X2tU8pN%g>$L{KN3Yz`6NcdyCf$n@eT>qc(y!?Nxt2Q24SmQ@5`PB~bbP*> zM4i)yk5pWw>f-=03~x$Of;<Jj(*&3{<}oN8Kby zVW0=IP)uKbzPkv+%QG-wyNqxl&+lbePvTxSmV|4g&Yy9+g-4nJC@$I9`Dm5#qaE3# zY!7;q3V=#J*3-sYjedJQZ!v0YS**odLDKejJh?IoSMhzd`J(sU(ngn;$6DiK6jn*u z-gM-j(h15ks`Z1bj>X-$$Xz_`Cn*7Y_kk8_vh&U)W5bb^LTVKryxzSj{2{VMZFEdL zpY{N1Y`KQV0d`9Yj$xehjGFn)`$tu;lp9Uq32qklg~~NQYzM75_LHAa$cm}YfN(Mr zn{})eY|%R0kX7{)^p!tP+X}X>bLJ9NO#OwDCDXMV&IcUmQI?kLH?Ppq9($mtAN`=_ zU6HTIU1MMUnL|EKJu(UjM|}Vf!0UF{$~I)jPd0-@E_)8pjyviZ)`>zz~^2_NSc^A@(>{cRmm z_;{b;5H#4Wj!-jCNoMo`>|MU#F}y`~{8YN4l!FKu)JS7m24&=}wwPKd5nEctSA5kB zLM-SUa|&a-vm>{hrV`G`iK$aLYnN8p&AEf|P$}^w6Ch&|@TGy%#g{ga^-U*S(NASv zPMkto z@3x&3T8cf{5b6|k4VpJ%=LPRv%q=chKeZhrj9@J?k_y^B9ru+HQrfzHS&IiIOPig> zzF7>T@SL9oH^NS^l=&URFM#mX4qGzhsdNnJqz5{GYlFIN^m4pT_IB0QIf|a9v!gIn zC=Y=xekmp2f_m-%ha`^!UR?~bYrWM=46erS#UNWqa4mS)r0xn$72jD16zwCpRJUa{ z5`%pA)#~+NE7Y0L)bygt>Qaz|e)|fY_AE5F`gD*iz-E(U*nB=L#Sl)-{QLeFwnh&4 zGrh3g!mPUM!}Y81-e?#!+}AeOk&Yqrv!09nW-m#CNI7&YG232v*~mpT?=aLa6WE7meK__@%U=)DAiI*~xfk3%peM@qItV_z zECFP3^IYhn{CcPOH)h=d4}V?^Trqz$3U5!Ii(RI;nY7PGO%}&`$OK(q8gJ%~%W>0P z8DJ&T9vi1?*N_iIgnS3idsK7F?DA^TeMjzq3vn{2F1`cR-#;{tMyUiOpqfQ&Z9 zH!ycBtOrrHl(|&k7_LYRf)|{s&TD;Yt^6%;rJ^=985rr{hyaIKBKW4Wr+pV1`|x^> z@JJjMlWOLdNgLF|R?{%01s1t7RW3BBO*W3oS(EL`qu6W*cW9NX68N1r_MDBPi5A+K|;8*m_5UT{!Z+B|B`i zi&_n{L&cES@WX zYa?zXTs!7C2x~vPqer1d;Z-GJ9IkTJ+G$UXNp(>Qr0PahRt6m16pmc!lv569tQlO} zT$f%iQsE~s%nZN-i3iy1VUJb_K|C2px)rC0ykW?5n)RrQVY3y;Pue)=x><`8Br_vV zm(Fw3^%31*4pAU^7H+=irQQf-J(qi#)KY9MJAf$?H;}5~5RICLD2421`iORzS}&d6 z%hHHl{$hKK)LC9j3b37;&v6a_G}oYl)qUoItC;p^gBwN?#a!9Gz`+4Cyd*r@1+4Po8H{>-e$1l&3QO6LB3@AeP`aZpwmC9 zthxglyfdQ8l~U|*ei+Et7Hp{ZGMEBayh}^V`a(3#~J^ zqcs|V;h~cKFnCd!eQ(KXu>c*IAYqeRRaICx1CfWKuLT`zY=F>u18oh_z1=MvLlrNp z&KqnH`KTwylj~P`u7|S2ZaB;S4Q7AjN7d|)-*@C4UOgoz5>sJ;x%O(O)$(|c9E=cO zr5|Aa46tMmaO?!dR|Qi+@wH;x3)_9zxxT96@%UX|r|e1TtEQ}V`R8mBP<{2iQfx8k zwPQ@k0g=~Voq^?z8Hz*lz2=LQzALQ42Oa5{BtMM~$=$DFhm+z6F6yVW6`6}hO@ z0sCJh&$mTg`J>CiF73i0hpW1xI;q>D!$Mlgq6+x|tFh&4Ds^I)YK4U9I?;Dtd?MMu z&C3o90btd??l_<5eNaP^Qi2xNWHU9UiaWY-@VlBQzw+d zM3jZ5dEw`+Ac+np4!lDDG#KY?*&@toB**}6SKuQ5YQ$)(Am)NnMp37=(;h70TFZ7z zTdQDSl|-2f^%OdNub0(EO?xLwbWld^7 zRk1}y_$%{D(aX1|nVFU%a$OgeE0(*aoHO}4tOP*mW(u>ci;(Buma#KApn#n!T>zaJ zTCnvs<7!!Hir5yad2?_MT0I?i#T|1eW3c~}mEEk+3dvRjQe+VprA=K(xy8ofqlUn> z7UT@mxwS%hu=$Q12r+AGHX4W~g+4`zU_QoI-`INeRM&AOSMi0rj5_75%Hlk9mtyyE zUMC+1I+iT%!J8W`*ZjeG51Mc-(YhKec?!MIy!~8?{qCwkI&NgkuuD&wGJh}Vg zsU`Lv)=pJ)De81d21K1MS%h*X4`sZtGNOM^r7FE>NG#6L*575DaeW92Y)wL6*e zE!?eJ;y28nS*B6VOhEb6p|EAX{#nCKGGm2Om|RBDUfXwBxUY{s(f|&*hCxJOvC#c9 zBzlbHBOIt^7zPJs3dcjkz z6``}N?9!fI;Pk%Vte5J6!MUCDf(QZ5lh~ zAI0~gn2v;cg}gepUOxn6I3L`u;hUo1!Z3}eBsa zzK1Y7lZ3$<#YUA19G8GGFKVUtq{^Fu2tK`yTY%vY5HB;nyKO?Q$jQ1~ zq0rTaw{Yg{x$_q;K6&ZgPhDQTa`oEhUSGO#^XX^a^Ld}|uQpr3+WJQLzRh+gio5Sm z(yX_&eS7Bv^@+);>6sHJPt9`99mb0?L^)w~@bzI#&LcY%-hQfBIRX!$+bir;bB^Da z)euI%3ZjKSSpP0s+j1%|Y1Af24GrxBq6t2e3OUeu;Q zRJ>I-497gEDP|b&Yp1=gk9ZKG{D$6q2eeq}T-@p0BW3kecu@mDa^-XHthM7?&)2UsZwxH@{vrSB5W`0;253BVRyU zKNYcDijbS9s$xnMXcj5*Dc+=%aG zDE-K82UzbgSsKwA6m5JovwTacD>8YuhrMM0!daobsMl|hQUZgnt9FP{v7n|2)sCmr zx8b9Omr1p!RJnc-c#j9S=cfh&+5vNDMl>)eP;#?y6ul{(F>i&VA!}mVjjH;no?WZ- z+}II}mao}Io|dQTj`~HrA9Zmm&q`gMJjs+uF#@(`aeA53Xk)J(WXuCv93PWMj~=Cn zZ5)(UM%`e5*FnPyb~j26yv-cP8aZgIlDxY8)G)WiekQa=zluOmN?4J8Flc1Q=>qXol1HmMlb6jh8oZ&jl6y;I( zH2X?tb4xgp_im9KXBjI!(+I_kBf~+Cj?_y~NY(AY2L2-?zCXOoUv296jR}g~m~?ze zoNRF&R|Ug4?A=kM=&;$KX-sy&7nGs{IT>WP2g|R#bWNp;X{q!KX^02)miG06Qx#*k9ltg_6UX zBJUS7o(}0DmkIZ9A8lg5W1fyQDG>thygGgl#ZUJSy_r>-#6EHbKj7eqDQ2QBfmO3oqSS>S#=Qd#K*?W`y5IxYb^7 z4%Pc5T&2XpMe2##+^9Q_we0WP9TK7Ix7u>V4|(g4Z7(!b{SMkCJ)1b8H)uQr1_4F; zIw37v*K>AtdZP&JC*|fhd_HP1UD3+|U0vyQ_$3kDw4OZf$AGN0U7nLGy^a%- zN@znfUftsnb7i{lUdOKh!eN8}C)pFIKO$9IOIfnA;u-p*DpcRhAsuCy?Kn7}$fFhKB1k~>8;ca~ z7WsleS6-NTQ%asq)|caO`&b`2%)Qo3&JTH_ICG#Y0m@SWRsr{jd#W)%Eb7{f-pEG< zZ}~A(NNF~Ol%(IvAF3!R%~WG{YMxiJ#_WV% zbaZRO-txqmTjbBAmTIS~6ObVtdPF}_px&XF3zxhv$LnN{(-@V69_hV9>Gr3QJpodU zt!`>YSv}z)8&th0hrRa>bHgBI*Abgq14e3!8ZT3adRHeyW zj@KDi#SReL8GUu!QCb&Z49Y@44Mo>6YCPEOQ0?PU?ab%cccJzM0|#L4r@35-u(x*WoB zRxmcP41oJe?2_AhxD`aYeQW!-MjclSfx7fXH@nV>qm_L+?#J2l?KqkWUwFYfm|<#i z0q?t^M_;Z}em9O%x(XC{*PC%HL+e{{49{CEtDre$H*+Vp(4BKJ1~R1B3wZL~H1c<1 zSOOr~NmT0y2+j}cG;v%lO-2@tN$)u2%rc1$t))sq>slnW#9`;Tl4k`oq+Sb&z*vxz z4&@N_{f+%}{wkcZv2!AB(#=%8h;A}*B_~pUWgB4rUx@ zD2db}3#t3b9eyXLZ_X*Z%QUl?R%b?-w)u{6f0JCmSkovFrTm@yG^H9j(%jQTpkBjm zNOfIu!G}?vE~RNNNX}m2)znYYzB|@2Av}_h%EC8PJMEplVq#ETJ5D)GH#ht+qJxg* z)EpvzYcuY2aWU+uq+8B$Z!S@U0TG06Csc1p1`xZcbyrfi26Ai()NqUR4*!3S6m~(j zLtc5Jv+i(*;SGP@llGyM1P*8ASPEn$&nXMVmz=IVSHywCIjU_f&6M^5Z*sNBD^xf+ zZtIjPF4uJ$0b4Gg4}dMuWdcGYhz_qtEg6 z1!1KwP&4Bg(_v1wC{Mh5t(qxa@R(GcNs*=$6SQNr-&K`S_FJt%VcHy_x|fMEac$ml zPQ;f4-8c<#+4xbZ470|>n8mWQi4KrA*&d+IO_Pxoq@V3=Df2EZUBAcSKl;)JLW4B1j-E^4e_xy>~ zG8~bh+>`RLi)vKVfOC)!y3FRqVeh@P{F~Vwlistp>b2RGCtwdzyP1L0;jCmzauj)vb{C1sDevBmf!O&0bdb@8t~s%090hQpjv_ ziQ|zcutHE1AT!ta?nG0;6>xW#3F|evd}`EaNl=NJ9i<6D+!H8%H>*u&z;=afpk`;G=gh`L%}$fTCeFooh*M zlqIe9nrl6g6}PxNIq~p)veR8=?G}HbMcRE7Z0n1p*oMP!*f@+rzvj9|oiRJ!j)KJe zrIO=%`HaOl=Z1BH?iIDHO0%TYHNp$c7&CO=SI0(0kF87O6}F{YrK$tM>IrNBT?%YZH6M$p_$d!2L)`Z#G& zMfst&g9>%-)GDtL_An#?Xid}&@>Z;u=yX_!zB6sG?F2<}_Zh@&E3mr*WK&oBgM8TG z-S^DS=HcGA&wGivGK!?D>knes^GO1Ww7Q~l#Dw*cWk=d5b<32NO4Ml*$7;-!{-XEZ zJgK`$*9~cKi^@ou=VMYaRF6!0g<72QPFDLxueo@WEqsc>9PL`s+Y)893vk_);T%esJ)}93gNC_aH$C>|rpYxakQ&%9LMO zuT}g}TWsT5!AC)@=f%hlb#J2U?&a~}qsUPghS^-poZ9L9O)tlVbrZ&r?WGL zvyU;ZkWv`|C<)0s3(~Nlb}7rHg3Q6k-UnqCuU!|tztWY9OeAfb8`Qv+?FRWXfX5eF zEdNps&~qz&9JMJ-7;|;XSJk(HRd>u-zXilxD+`A;rtwAyVu0&+ODgX zqe}L-E}J-O>Xlf5+qb9=6k2)6?+PLBIvF*Ca2=0bwf%5ptl|f)t^=g z81BOMb{sjTzZ}P#sceUvfn&2UDmQE*&I-f}kn-AXA<4TO)`1D>MzHEfNMn4ws(v3I zky=}}euLe{oEt52_Xqh;iVn-V&!er{A52`TjdUH>`Id6rJg&RMGox~M;(;YxJ zA4|y&N1nfp`!nHJSN3Wc+V`eVg=yKem@yI2=LHyj$hwtqu`dGm7Ts(-J1}qzDX78c%-NYt+N@XW~ob^!NF-JK`hcZG& z+cw|d3zMLA{p!-7fUkkV#9ZH|E%T!!PY?{I@~&F-U+?IO#(c!Jxce1b;Odg}>SJ|m z<;cS}cuQwVA}8BP3Xu#iBXBkbut@J4NIn*rKRL+8q&F(JH$q6bltM2%K_*vsa8EqU zUTNmHS!Em>Af-wt&&*q4cFrvVNhQX*yU&ediPqC&SW5M>7^b-K{@h~D#%xWO7Xm-) zC4rMvMSM(&lk z^q@31=DlC8x_}uXwi~Pv=CHwc-LO`~w>R%y%5utrqxZ!qW<)sRLVl=W&P8tbue?Rg zuLzd=`&FXB%LiymcUai^!B@{ttJ03t;#7EP7ulTULAkq%3E)`kcKo_VA#~MxXCJVl z_W_pS$!+g$oY{8MkY3?BK-wt$@sM*aynaKnT|ulXldFJ?l$%-~2VwF?-07OWamwmP<#xY3 zvB>9fC9xSlypG}eJhCd=hd>GvbkT=tj*U1L)LeL>zV7|*uo`wFOC7EtE+T7?m-Mu@ z7&?AZS3FqIa-sq2a2|L1l9yJ{Oaec}-HS=w$xFq7P>e|r5uOBnAEdb>JYzP^r1T>h zw_8D?`_`5mMLbL;ea$KN@H0^N!Xvj0Jlmtc<%+0bvD_nngb5 zG3iB)4N*-8v{v4!-AijJ-M8kfK}T&`0cN2bF70fY*(k-R6SJfp><$Ac5}~|c2xzjc z>V%Sc)2q?B)KzZAX^%DyAhpwW(Z8fq-0>&p)Wb&)O6gox(}=Q+^rsQyk43Gsk+hX@ zu^lbqJZsEwmx%p#4_qdgSUB0xIQ=mbOr?~Yr>KTlAO@--_}BsDcI=Acy}jufpS;RMdiL*j>#UMe8?tzzQswiI}y`YzVO z0@U$$WE2D~T+Pe@Twxrcn_Sb^+E|<FxK$Or=4V-uM2@u}7px6^g0rL>Q#3bS)fIJq&k!*$fI{Q)7N;0?6c5#<@--CF zQWn~$`v_Ld8dcC%OkrxP4;GVaRKr5$^!ft1z=JSGcmC6w+xc$=11V|R)Xr}-V0U26 zYX=P-vtnK&I)&ImLvRa(X6LMUIdu8_kv2!!bj+a%rfP&#s2Fs5ZRSkzLTM~^IfJOI zzTW2I#T(botCW}A%e8o0s$9yz8FiYoy3&)0`eY&3&zTVPl*_iyMH^IjM0%lT^SRR0 zD#X1*Qo%eS@jIG5cX_Epan{qKM&U;K5zH9Ea24NgS50eKMm7ze&2fH(-mk^m?iNi6 zM4PgieKhKC=-8?`<4?QM=}u5qCuA0RyPT-k(L9K6mQl19R z>Uo4vrAe$e3Xm~bJrhQD8>ETO6!gX%A*7czH5dXwCvoNGTOtb`w(|`@zRTh#2~~u$IpnpvW30ThIs3C6j&aWkP@*{0!%X&#JOE!&G-JPnbu`KhIxy|58ud^CBi+-sfQ)iX< zA_E9MiU(JMz@|^iiA^~@IXgXj;^gG)46yGC;p=|XiaY0mw%>QS2^ZYw+aY3B6m&BR zGk(iS(zF&)3bcAy7%4ZW-YqV?hyP~2N8fhR)u3rp%tDaw2gNz_#fA6C337!Mny2~C z;wTMNYUK=#4p*sdq~*2Ps?umYM2o}4vckd$AN~_5tkQzYaXxMO-QYr;To2aI-`+D9 z^TwUYTQ8)21Ksr`7%xm9MtC{iJ9cYjxjH=Z!rPyC=ks@#m$ho+*k1k;1cUO(6AX&0 zm3+o3NsNN9bkYm)mzK-)TC=C-OWrgjEGv0>)r9BRh3cNa9cFx)TS08%#nq=AiY&-Y z%0!^_g*?SFKDkk+elbH_QFTysn?ILD#H&C-T%zAj^(EXaC=Ywc8yAn(Auh!;^!8*#V`ub`B?y#Tgv>7n}Atc_M7e4~(z%Q*}=(ohj^cKI0Z(H%&nsZIBS09}oof$njdTMl{u5S?4O)V~B@z5y? zx!d6?HBmb~IbwfLjTE|}iqs7$pNos;J&^!6^&+K49v{O$+(vI`mOn($eej+fotPM% z7@ZoO9z9{;#fOS>zr!jKqj&qZ9|fy^(oOuGUes&%)`M;{i?@R2!ju| zdb^ym44qqMwX?zQ%`t5kA%0^H`BSsyOs`{8VZBYQhYo%6b5?lDli|oZrZyKZp}EA- z^_Wu7H_oYPVBIU2^*cQsbZ*T6s~E6kGPRna>gUW8*E{DzM;TY-8YZ-;8V<8+h8jPb zx)|g$P3Ck2s{uI9BO5{=CP5R)dFG@yCabDHMezm(KCee$W0rI=%~~X;&xKShhuqS> z$HvA~KvpXbI3z2$9i|jDZZfk8sIbBGpC>o)p zrD*S%G)=+&Z(v}OV5-WwTbbYW83NVhu1^0>%m)^BgN7Ylj*GP%5=BEwo>&%AS#s{3 zgFZzHS_|8_o?*;N+#K~NQirHj9od38`q2eHodg6OnCVBgZU_ijYV~Arzds{|YJ0*Xo~i=fL97VGSJ^3rV*9qxt5&|4`ycO@_aXb^oZZkEU=EZMsV zr@>1*MpYDBBms99?xmX`7E_CxH#*(5)G&b2B8n@7UR-W;x)&(vYAZ}P-4!)$$5|tz z#$bq7Kb2Hh>x(hfUEmdEBByMtLfkSf4&0duE5srM4$jqb{p7~!NbXk#Cd2`a)L(4} ztx*|7{%X5;?2|jBSApa{37`1T?2@XSpJC^nC2!mP*(C5OL=RY!@fx9o0dkzBym)y8 zC)=~-0N*%+h%^%AXr?A=9shO>8Npy*)El>)4=IZ?zg_DDojAeW1mkkbZX9xJe;y|0 zA7(Qb-8s+uE<-NiA>EiptJN0_&h;y!12U&UfmIAtR9@+^Qgmo_r3Xku>QYR3yLJ|x z1%J`sq!V*m=BZ@{&E~{49u!ymQeZf^5d1-B`Aow(082r!>%ZUTYs+Z)cgU%HT$=Ng zKLC=aE@5D7=t<7uM(KfCEELqfyUyBOq%#PZgo873rHTVGMHM+pv@cvLv?$8aU~#^b zK&Mgj=~}wE%GDNlNE&yR4DTY=7v4i6lgVrXp@Vw2t+iE3*>C81AjPsRWbBE$ z5cvyqdM^?xZtGUIn3-nan0)LuwCI~wL&!CTO(<0KqR&OaaxJDTGi=l?t*?n0BC_9n zYaB_cZXMn}tixjl3?M_V2-J!yTC563Wy<%|Di2V%?Kc_WD|9@H9;@2M2Mu1+cyjH^ zTn-&u#XP436$yYC+D@7=A}d9wNI!%ZJsB(wUX> zY_JSolw2jLnrl`=>WJS7Ku-9fmn*xpXnbR;r1gy5t&{qIx(awLq|j~-?T&rhFdeT6 zjwylGj-(gR7J#M!XI=ObWLHBo-Aop`oyzs84OX^CHIEh;o{8b$iG*(hjpA z@!K+vbW(S|GJ7LPgVg1ULSKqda+IzuRcbIfOqQIWGPB46jn5XFo2L~Lm^#%vR|Ys+5SPJB=vore;ZNDtZlaJlb+*PlTJkj3_YW;q5GK!yv^pz>xJf0Rkw4 zA|L5vdd#(qspUJl8Xhq#>v@Dl?hj81ceKB8%aa<^Ux7_KMhV0+12GPa*G>bB5p@fg zT8M0zdr4WojLZVTv#13Vx5~s#mGzN4eHPQqgPM31spk3y&9b0LgO7qb#8XfSp79g9 z>f0${^nn2)sdQ_t9;yKO8}XH1#|p5cK$(IBj=SaM))ULiWB6})*l%|?{1;Y(%zq(i zzOcMJHiG9b^xcPK^Tb;nuaI3-dRZt`UGSkHD41a=zg2i^ zx0_wRx#_P5;~Ys$yLfe4G-%cIxtPMyZzerLJ~ky-Slm6yz#S*ud;=G0ztm)brf340 zD13t5D27c) z1j+KZN}145OakoDVZYi{tJb~g9gSqS$o{XedH?-RjJ^H$V@;b;aJ zT1|(A1p%daepE3fk@K-s0C0)`+@%?s-Mh6ibGKHK=3U!3S!hFXm}WGVal1{&ph2od z6=9l$@e!L7lhCrubTA3pB@Xy=_?geGUXGiaMQ&CJX)HgJ^6N4*%(aWYO0!q)F*bo$ zlXbB3Lfb4$_p!EFSg$6nK-r%QNG+66^d4u(y`|<)F&G3%v9wX)7;E{q^&w;+ivXyd zR^6$?_XE4xt!AN1X8U)?t7qwUCM{u&)~05qU&z{Bu2JB%IhI$P@%P26IommznIs~A-MXPAWw5YR4CE~OX3B+XPW77#V8-6n{!N*TW#zA_r2b%YE+oL)%o z6Gs{|I_D*eL_OSo%^XCgw!Nh|Mfy(t=4g4NuJ&F)Z&3qecnAlpPEfl-wqy<>erB!lkW zPJ>z+IH81kmxw8@_bN&0lw5H)ptM5^BIHtQ1o&VO^Ru~^dAVfvDud=k z5po|=$$Z%B@~|BDrY54@M8ob9QzPv@FqU7#G`p4xM|W%Hj`6No8!4`0g-*4iz{+RX zHh0@%4c0H~DHEuw3s$pRJhg=N1yd=M!a!w0rI~e0cdH9Je-}crT589o+8|#|KF-DN zmDFK?qRe7gt7f^@ZS4)3E3pR0O<&D`gegw(M`7gTx!WBGrVU=yEF7niJgo#kmoG|D zwHPOX%t!%9Wwzl*8Xg6+%5bK80`^9cLoUeRgLW{-7MsF~=BQ3a0g`13OWDOmMa`ve ziC)}MjDl27LB=N;91T>SP?8$rR~6L*sp`r_P4`li1<96=oV}W4$K|9x$i}M|UQiIF zF2ao{sYMUz^=Zz1ZMOdu<(<Cu^GY`I!8?qzb@=S+n- z+JT^XK0pYjv{&`%5o#HxJ;TM@UPz@a2?;SvR1me?bJl!2OttSZE~$%?a6OC~)%v_l zd#mpYnpvYdF)uqon)>TOqdGY++hMfXs7}qxG;GtYBh!-1=9kNaCiF9-+w* zvKp4cQ9Hftk(tRYk6B(uv`MaxW=k{6bV&cq&dn%91`i5-E272Mr@H7AjIm@Z%xI4p zwX7fJ;#c)U?khciJ4<{n&C*dlm&0m__WV`9*-O2Kw|t?#JbPhz;pFmyI%F$h{qd7d zjShjJ$oa|TQx}%c)OFAj{50`4U4O1#FPvRIb+Yif*L7Z=FfW^aJBV6-V*8$*T0S-7 zyiZy+gy+>(3Y@rQ5$!aR$66_0RAZTp1P)=pr=qq>1mTSkomI8P7)bgnb z`zDD~gjyvU6SL=*Pn|Wd13$?&Z11PeE}uGQUao~nVBgJ7FE7|(uC?QCcc+GcF{jAn z@)j7iw{N(cN!t$&g)dqUi(9XK8ZiMR_wXL|F`RhR~4cGPj%q}c1*fG&n#9_2v z3!<%{9d}(Irh9F^@)-+A+fUYmTAUz-Qmq*#&9>Xrh2;fHGF&tX zTK(mwm(NTaoIxl#2$^134Q|`P2o|2twYRMy8f$?WA<# zRS;KqBaU2Pr1cCPBIQ?(PegPq#{ z$KIE~$8}YAUoEyJd5xXL*`H)5auSbLOO_^al94o)Ce{|s$d0p3-po8{UNkdr{N5YM z$_8m!(n29Dg_KefmO!8^rR;BKmzF z4rpfHyZb%&f6qDhoO6r1?LuIk(2Sl|S`q2Fc|a05OA8-rQmC=-=7ET;k(Rk&7QlQB zi=?CET7}t?Qha}(rzu6giiVNShEjSiXIbhvcikLOdgBTTjSSt~FK3&X zY57S|Nsu*N1Fj05UkuSZlGG(O2!H^>#NB&&kQ0h&?39;++L%6Tq8BM1|44}iaSP9) z&}HowZ6Eledi1ApIMmT|+&e`j^iapXP)DaSf03I92Eyjn8o;G_bJ4}y=MWLQE$N+DF+*puJ7#nR*zxhM$7OIZr?N@BJ zpk>NDOc%`KT|*Y-uy}H82Zr_csK~K5*q&)S7cF2AGaviI4;2-gBRUs~LV_RGNo51C zcLjdgHy3WUwdR{!cHO-Dl1p3nTz2^td&5^=b>Ql2uD$8zn{T=Gwma{-`yTGA%^0Ur z%F*uBS}y5`z$xV=9Ygrh)j>Zx=|>m+=%ye0=tmFz=%pWG7sG!omvr^f=l%49mfkf$ ze+}YCH+|SmA9k~cv;o~wnndh*tk`|DVLdcY56#m<^YqX>y)?;wnq)ssvY#f|9~H>* zEcvR_VdaO$!r%pts2uLKj+0-0y1+954X9>dpyq)5fF-3A00~RUPZuhz2I>Tlm3hFc z+`-)!(a%S|5Z%&C^ByGeGU@@YEMN$P!6^5%u;JnLVNGx`BzWUPEg0bJZh6Qpnxa}w zD8lezJ;&o0pROr14r0t18jnN3sT_6H;+}|LEEWdegWSBKwdh5&%{6kytgYwa(t2;y zjxt>*f5H?19PDGx!BQ@_IA|3LMj8ZnQ5(Z~Z(}@T9&0_ZE@iZR@31xDx z_8uR3%szL^@~X+idRW#U-ll+_@K=L6+>BSDFH@l78+VJcPfEjR&On1qXo#xe<)@Pc zx7eP}nMT1yZi%|YWUz;FH={aTHi8v$vI~%KVLFS2bk?>C<{f2MKQR*W_LUD4MKIsk z!9#4h*bb+Qc-$?yJ&(sriN39bAaWY{P|`Mgk1A=8nd&_t%Wm2RoCVoDATjm^lz0L8 zuF|^MO?SMPl+xG;Lm*ksmbL8e&>*B_!7XZZhCnUN!w!RMQ>x^OD-~eK+c=Br8)VT@ zZ>s|)5@3{(z=49rddKvRUGiXTnVgFTKSA?!5{nC>!JL^k3Jx_LyCrmWOU{@#a`gT% z+n^@LLRVX9)*)ZY0=vTw~M{EQB-+%ca6P;lh)D7SiDOG!%O+$+cszwuBB-@55$AP!N z!L7pLJ&Py7-lJ&%++r>huy`110rXyEUcTBw9*^j4@*t zj0_G8a{O##Lv=ZHhK?9}S{8}Y^ET+P#go7<(6Cay+zES#Zmgc%3$^W!(NoEt^eaP~r4daPfG{Vjfc*U`)kAZ{xuxw+-UA(KkWF%6qkI=}RsZn!(Gj zGmaZ7>TXtv?y-WaE*0FkMZ5blO?N`*#DP8C<=K+Kpm+uVgpv=0IoxySP1^1mq{Cb8 z7B}$*vG@#<)%CxpMeQgIjM(SAWOtKFLezSI)AgRJ2u^Fc3`SoR-%@@lIj#t~PC*q> zvU3Oas5A_HM*@aJFr~QQ)>;|E-`0S&hc)?{w+hoog*y0GHidKw(4mmsbFNH^k`KaU z-lV?cJmoI>N}W83B?0%nE5nLIN)yA~@{)GaFbgL|mjUNk@HUqbfK_Pgn)oVPwjpjF*IazB#D;1@Of2CGRu#B5`fT|!M7Lo>@ z{9YxsPxD7hIjq}Q2s7B{_6__o7y|+-Lz*&sgK~u+L=J#nw<7~)&CEE4dq5PH&Xx*u zG{iu6*Z$r<93TZ~Ia(qEPH*hx(}>$NZ^-gJX86c^!BwTK!F=iAbc@zq9o$n0L4=Vr zF*ub7Z$`mT9{{6c?odY zXlY|iD-B65-wFi=oyv?gm5&zYmrxzi0_Y~?Oxx7rgXQ)=4dmxgDCPA4%K{Db3JY=t zQ_i5p*XkC$-N1CX!4w2+F$`E9H)Clxx1f-O0)U;zTNWUa55HDGGnB!b*KHF*b2yU0 z5QC3_s3~UChM!rDPgmX;UXBcoZ$2v7ZGG*>=%UWyAUqKxp$$xJhu zdE|l4Or@dT+yuf*TF+_xwup+lv@2;^e*K^-B7s;iYUzOe{8k%YoKFJ>DZx-f`lh0U zp`>Qcq41cR)J5zx*aW2EZca$uLiwuAP37_wrv6-;2SeNum^lDvjQPQm&F}5P z6zU**Qo#$Fgx^!dUh|*8*saho@JhPDl;^?##q91C8q%1DXTC`b-)^PQ?%)=F7t1aU zG>jIfTAk9qEL>vyfE>Uc2V+DKoxB%eXczZx6UL} z`drd>^lLji+Pd+7ogHn(QVMuVu8C<`CMh6Hd&x<4decEMFv#S^gb(T#KBz1}6&uhR z7|_pbc>o9Wp7*{Q2lPd3K0NeCp)~4FvN#5!!${&XwhBX*lrRkUmui=w~1Is7HXunjOmIN9)R#+*f_%hvNDu(v$0zqfBpvyEBP zaqYzrD0y%_!OG(gJKHi=dd{%hObdedWlZ~kqq}-1klJR17E-L^l(vIYT3WZ~45Mh+ zDa%#K?DE(fkn~^s1xjXr#>lKbn9Me*$*KiZ+bcI8JVNjs%bwS5_)%?nZ~`9KczhvBgkM*(^|qc6;uv;*)*c~*)DS|h zBlKUb^1YrAGRB@mjwJiOL3!S&JpXYGlrz?~o{&cf*+5Q^CUT;to{&b;0DqbYX*_cy zA&u+LfS)zwL}N`YA&qC%(VwKbZpJNcBPZ~4g(cNONt3dqg@pwyX<=bu%-<&HS>-m> z*Amk3&IUqcVUClS8Ku&@wvoE#L*zn8Uj>G9hD zh3;%o3a!(NCbm^Cny1{>Mkw}Nwb%`M(G+cE-y496oNQ>$SafzWI{FJBCPI*o-oUy)cDdQ(Q%3(>NB3AU9yw4?Nb@$^(V-Ecu8ywWj?T``I>AoX5Yh>4 z={N`4vH@CaJ31kxt_H}yriQ$J>b1LDo=Jq8+g$y^$DaD~!^bZSZAmYD;(0H7`r`M! z=z?|4FMau&ZvErmyyRm)cCrbQ-+kS}w~L)mH2meyzWBr&Z-3!?{`viVFaPolA8EMZ z(Ffl0vd2G?H~;za{jdAgwc2wpdvN6QUwZYQ?fCmYTiE;jU%&sQch~iO{Z}tOv%BRV zpV&LL{)ARI^ltknZ`-%?`ge8p?s?Y(nag_jUGdj9b!5$t{?ki7`{d~Ocg}jz%wOoE zwRipep@GKxUP>-~(T(r;?c3*mdE0v)zWe%Dzqfbp$=^QbW2Nbb{@3ouein}E_l@#^Ol zdmh^L?HBCbdF#*rM!))BpM2^qzxdRhuetX<-T(9-`#*5ii_IfBgPf_m^&c$zOgh^v$o-ZF%9l>Koqt z#jdyfwD@0-OfDEV_uugJ{A)frFn?<(RQLJ+xbpk2`^KIRU;4?#r>$Mn3yz$#2*N)uvytjR^@i*7}pmyuUTi7z2vFruihHLCMF(Cda zAT%NP`P2Hbu8oA;N7o#{cpV`C9=O^7f9qgU$tGBLo8b>E$GRp$I^GS%1g(uHKKkR& zkgL{RaBi)u{~)X zc*$4p_>Y<2UjM6)l=l5_uBS6y`_(_5`{s3_n(zJkt)D(~=eyf`|GMtVmyb^$e!@6< z{)0_#i9Iv&+`3Oqe));MKY81cm)8C6_@n(le&16+`^?|n+tl3tve-lCe(Q$~Pv7_Q z^G_xpTsM(=^qVjK!tUozw>|Kbwf{38`da#|f6ZS%`>Hp-`?YQBzu)LmI{yc?^}8}t?qxM2 zfBX+SyB>S#-(2#eBe$Pb`{aXq+r6*Y`M=0#&);y*2V?ht_5f^+`h$<%^`_Bxhu_%q z?l=D3zg#f5?&Qn6J1^zhrx$iH#&d)LM<>ipY#W=4McWNCWy6R&^xZExKFn&*Aw zEkC>Ys~_zD;lg|Fy5;Thn6<}v&uy>yudB?*-qW;r{x3(ieC>aK{)a#L($*ggT=LC( zPkiatD{ou(*!+`!|C4h+^XZ1mdMUR zGPeJBE&U(+)VJVFS$m;9i+bEx#y*(ZOo z?kf))4_pJd%yFwpTGZoue*N#?Z0}}%Od-qdh4Hm{ac^d@!QVz-~Zayr)K_T z|BZJn)V%$wEp5H8`siKRFJE%U?*{*2!TmGcuRQCkFS-BTfBvVBe(n0kcwC=+?+czYSpW97{o8*S1|j6RXLY@+|D&I{ z`r>$J-4)G;znlNh7k&OMAAV^3moM7$iuvPjdGEQu`r_v^AAR^?d&4VV*mv}SrpMcV z^!Vfd`u%ra`TD2d@wXqjY1?P6`0Qs!uc-NxCw^LZY`Amk#B*kwk3RKpfBf5y$UV;A zzwqA%8~^D3D<6IHa~^%;{%`c`AG_%OZ{PUJTR-!cGcWkXcidO+`F1`F+}3j!pZM&( zpL)qRkDfgCpXX1#_+!~efBo6N>iUPzAA3jk&d=X){GOLT=R0rzo4Y>#LUZqHH@#-d z-ky7}oxJ@MH(y%wXnW@?U;XssFB>b}dH3sL&wEpP=lMUpslI ztpC7QwD3JI{G#@{J)3uZ=<%mUUU2S_^j+UPZ}0YBeC)yWd%qKV^L*^@?|m5Bka^$N zXCrrXxUc=QkH542=Fe*%I?%A&`s|m#-teZUZdv&3hwl2qkKb2+`KG&`jHd26|K$y@ z{?X+N_iz09n{M6uyuW?ogX`u7_x=3HQ1`BPG#x(YH~Y*drzZaVUa>iAR`M8bYBA_4tUPlOlse^xjbNu;~ZJ#9f5wc~H+*e1o z6GF};gg}~2_`C@i+DXz_w-Npz*RmD9ts^HIYtNV@&14(=**r;_YrBTYBdX zXf7)s+O>|gJD~h}D8E*eU*{{or>uO#*M2A)>VW+~lwad*f1N15-dp~Lp4sdjAw9ix zCu*>QfWooy^}O(glQ7ht@nPi`{N{?W)d5*!e)QZ8JDkTPuE3aAF&rro>+r=465+{F?=_jj}J zKt}vI3`IA44nuMt`wm0H(|-fg(H8SCN+;Kh2ZuUK@I zHeC)P5IIo;s~*y9z%;h&6k#|DZjqDY5jFzwd4!C0Z6f3$B#--$ctGH(VT4oDNJtG( z=NW|5pv1U^kcR)-LdZ5k8rN+H$~qJNoCSYs;15W(IOwHfp_u1&Zew-A=Qdmd1SIJi zVEKSRkCn{yoMRv{!Hhk{(!=LdWUR|1 zbp$_~nh1f_4GRH3Gwiv+e$UX~*Uv&PvhZgUee$Z!^z+GG@DO^6@;i_kRM2#P4QXz` ztKP?_2d^Nc8OEh^{WGOoE=oRsC;UDK{+tbepmDa9w+f)#gb{+}+sS$ipPgi^s~%@% zGdTg{#B~!?1yMsAdlJO`3@#m*VZB)V91JHRB)^#!2071z;bhRdkKsFPD|a$h99}=f zzQgNl*mt0SH$k}!LLOz`q4D2hWdfu;4G9^vyq4vKK7Ey?fu`IAQ%ndD4|$BG0jl~C zD-)>V8TK8vue(?pK!jhi?>h(~_p|S?&HW2Y535yU{W_Zv@}KPaIfRglSsMV%9QOTO zLP(L716XhyYybH$R_yr&gpfr>x)%~cdfD@f2qDjB-!CSFe1Lt|2q6!!J~jiz!UIA` z3n64XO9OaxA^Q%v^LiLaLdYe6Pwe@ngpe=U2+eQfaK6~Cy2>B#?-a!c2!M+3ioyYppMF{x_dkz@-el~{t z2qB|TFhV^cm$UKjg?V9V_7g(RXL^&>c^J@uZGKl0LWWp5z#cup$~iy? z`5@zat|o+pSvl9h*s*f1C4_vAeFy%(g?%3&gq&pM3=%@V&YlkuLe62|0m^^J$~;I2 zaoP7_LI}#4gb>(kKE~3=U^TMupo4sZeLn>2g5@10guH|G1@w_0Vrj++A@77mLkO8r z#$gillZ+0pCxk>8T>kpXJi zbm_6lTiV&Ht#F7G(u>8Ao&g&XNO`7`lApTVa<*Dl(@nNjat$cR_gu%L-Pq(UJJs}? z*z-xtc5eZE-b$X!-Y4LYCEVUFbB6mmI(zp9KJMX<;oQ_HWWs$N{K<@M6y79ZV*srsIj|P;z1_HXIv|qkfWQZe}g02V*+Ov2G|jFg>g$xsoM0L(k;R!nMY6 zJzvZjZD}hH>9-GE7a1R(NJfUnV&lo^SR^*8X6|B{*I{PJaF!>-WF#IxGBGu@l04J# z=+t;*EUM<|WA&WLhOBHPHXWRr7*9mUhmzA%o)%upayAq#$DOqe&@nczpBx^Uh$qw< z_VILJ9GcP{9IcI$6Y<3GR5YF(8i2&x*s$*9g&knIHm0)>SR`+Bc6CDqXNZjI2$W^t z&$2gC!YtWX>t>M|h9a0tm(uwbON5%NeKnZ#sN7ORDJ!yt6bX47yi+wK^8A#d3^W3jWRU2RH;k6KQ54aZd{ zaw@3A&gDzw)2b9HhW#O5nYX8OC#!|hU?x>`Ltr&Xoe05dg+F0I_qEWX#s}_LF4Wl@ z!e6En>W0+x3_4^KTzj!-nFY7a$%^z^OB0O8S>m8tOhLG_7paPu+)PLfh!d~{!RZ#T zCcq7YjEjd{DB_$=NW?EfsQx-OPL`l&-^SG%*7&~0ri1QGl_$oYu$G0LcZEJYWV z8_XUgyzqjNT7Eb=7P4^xGhMxq32S$;F0UPEV}*+2g2b6MSt5KM0=JFj$5C6BEX7Dy zVjx=KFck#v=1uAj0-M>+N}zoKurbP3g6sh3J+3*;tpqm8P3p2bZ{4a2TPZ!Ym?}Zv z)*B`u6ot%sXqpw{}y;TQ@YjkG11%wj;AX@45YOV$w3X9`|&12ZoYT;O_YZUk&! z4dIMklreVKUL3&K)sTZemI)cV-8qLcb~&?9Iu3iZVYiD$E1Z|?NmYzZZB>lTxwWgo z*tA5n6bv!C!=&_-X*kW=h>OpIU!=&M`dFe+?N9+9WQOY|E@}8*X;iupNa!N%2 zG~7L?_ZOf%1|#CNae39@GB79EYLGl|$jY#sE`cSWJfyV>`iG@+0GAX;b@eS>9R~td zk&@cGHV)8Lqr9if;Q%ZT`jl@I)zJdYQ?^m`_x1OM@lRFqL*PaMi!JQ$yl?kl@zwX#v;H*p zj5Y?@Tg1^tTF+!qP*{U4gTUG2BY5upNIkh+1-mBnVZg=+L~O#JNaTnYV4M{O^mUn5!(A}T>+pM3@LFFLygpc?FyRHm1(ww;%nG&PAWXm3MKy*+ zYr(K*O1Zt70cTf5+jNW&I)U!htfEoikfj^EV2(m=@3x`OgUE3w_O!rsjmYxL;{i!4)*Qq4)5E?bYKBm zAuJIoFDwbu13a0`BGOzKh_UQVFpOa)AD9Wry-Cgv;LkZ6e=wIE7=RlvK>&k?6V2&0 zm_JFE51kJ5l%JZW^_-cqp|fj@J+;*d;2x%LeS6BX<{SY#8=&pFz364Y-oT{vR|HGx z;LK8n1eXTMW^`NtCb)XdN3b19gN2|h%{md?KTIKR%IkwD}st5 zM5-zf3cZZ}aEyI$<0+lN4sapV12PFmC8*t|je|*|2vDwrfhl1pNg8m1I15vNR7*vT=c>Tv@!+TtY!fld0eP7Hud>XNwTbns~}V~sXR z)+oDH;8Z8fO=>y;59|Boiz&ri_%$}Z{GAUgq_=RdGEMuz>#YhV_o2~q-U);y-*Rk_`spM z(6MIR1>H7$D3#9Iyb2j$iapUZAR$l%av%Vrf!|$yWBk!rbS$j30^!gn9IS%pkESV; z`g-^Gdl{?%XcCkamUJg^h!37wK+fkvjzWQB0ElxoMI8S;3gl^9**tQ>d=t8#pQ2G% zfMjJB3cnA@s)m5|kdT&|+e?n!?qqe_XfMo~h2!m6H=ko{D5~EC0(cG{`0{^UxxI;4 z{-D$=TmBdFvt1kjy;!7Q6gFlZzNrcaHdMvH+^FIJ97L81%&tKQI%B$Po5y)1@fj;k zd5xlN=5^c5EkZaS#{?6#y&A;r*CFy*A)`4)8lv$ChK4gB*oBJA7vHv-g?9gv1)5+> zl&`iWhpWP(>+9&>=aFhweD2M;h2@AtF4N7PfrX6-ZK}W^M0D3Hos6v3pu-BKMDytB ztkD1w1OR_#jYN%U*{kVVMmO?S0j`2|HRE{EatsI7?!4|A8aF=D+^lVt zX0sS5Nh!t1%o&lMjN0hde6n z&9Y?WYeueD-?j?&_lo8~f7VCbPfg!iT{8eMzzm_)?HXtg>IoMQ8aUestG0pLR?)s< zi%>7d?W1eF76TiXNWu&T)Fj*rT73r9Zk#+4Nk%3oxiz!;Ub6gEYB|7=SuhJ5QFG<9 zYh8zCu3kmQe`!?T37%~a0t;1%jf47;th z$xMUIr7*U%^@TPnk3&O131Jjm6bk}W8m^HqqK#L3UUyu>R?`6Pn|U~Rg@uD;8p>I- zR$H+!%ek6X?}t_PpXQT$X8Za$Z1TW!K@zqCJ*9wtFkyyNh7=K zMbbc(j7-d^k>)9rdip?vjDLjk2c{>iwRVJAQv&25&UDdFS~TjTafQ)yFS__7jBixv z6c)c^y7(-hNEA$|LL{16eMxghhy1aIR8PPtLx1pv*o51IyiVM+%1sx z9G;asT+t#t{gc}|6#=ASAoxatlkzz`19xJGBvmG&hZGGD&J>?0@4P7+GVexJn{iWB zoALQ|%F(1pwvkNMt7)aZW}oar4IIeE=mE0P0ujF8e~zsiT36ezPYhZ zO19tU*1+Dk*^Xaor_EqHT9C4>l}{l<3fOoUkZ_cjNrLgARnZTEhXjWnOf3On$z&=5 zR7gmdJ>Q*`io~*H3%oU~F&tnUuV|7;2@4o{D$J6-!BsdbT23@;5J%A$hQ=dDA&!O1wJzJa zepJ${SF}60I?F}{$=9CF$x7hfK5wkm;YuwYec%ZS-#9mcok9|qRup%#hO`AOa*rq2 zZqTWZT7}t2Arm*!w&BtX%cdP8ld$6EY$1^~u8U8MA2Cu1YtAU_>+0SINZxeakwlVu zz`*Ey>th=!)(3j`)sX%mtlug0i~G!6&MW}g zU{^gYtP0mRR)yxyA35RZMU zi1EtFrhh!jK_81+3iVYo^5Lzd1OSf}QOhyr6Mu(DhHky~Ta6Xb1^M-w9x&dQ&m{>16ASE z3K5(`dA*>6M}5I-1{uV#=blM4vUz%nw z&7dQd31mR8VS(mTn20SaNv_Ipal8ZJB92w6Zjv-swff z6>6_%8%`+?mk?>CBHSY2v~yb=X@aweR(?z?CE*p;hV529_)^w>e@92Boa{1mWhKe+ zo-x@>P|r*;mh^hnFrOgt+=Z)9!PE1Ob~bku4g>jfxoQB8t5|EaEKT#TBYC7=∈X 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 a`%9>;9pA}pgt#(GR+_B}c@>KC#{Uc3uRtvT literal 0 HcmV?d00001 diff --git a/MikroNUC/20260228/20260228050256-Binary.backup b/MikroNUC/20260228/20260228050256-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ba52aad86545c05fc0d92594aafe57a73217b0d4 GIT binary patch literal 307416 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 )s__s&{Hr&EWE=G!lV> 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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228051159-Binary.backup b/MikroNUC/20260228/20260228051159-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..089e05cb3ba608459707ff68831e51a58cc3e102 GIT binary patch literal 307416 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∈X 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 a`%9>;9pA}pgt#(GR+_B}c@>KC#{Uc31wZ`& literal 0 HcmV?d00001 diff --git a/MikroNUC/20260228/20260228051159-Config.rsc b/MikroNUC/20260228/20260228051159-Config.rsc new file mode 100644 index 0000000..34693db --- /dev/null +++ b/MikroNUC/20260228/20260228051159-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-02-28 05:11:59 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228051334-Binary.backup b/MikroNUC/20260228/20260228051334-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..93d9491236b58c38b7a9c668f8ca79946e067ad4 GIT binary patch literal 307414 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�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 TW+TLvS+de>RmiJQlsEogqb)#P literal 0 HcmV?d00001 diff --git a/MikroNUC/20260228/20260228051334-Config.rsc b/MikroNUC/20260228/20260228051334-Config.rsc new file mode 100644 index 0000000..7b29bce --- /dev/null +++ b/MikroNUC/20260228/20260228051334-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-28 05:13:34 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228051609-Binary.backup b/MikroNUC/20260228/20260228051609-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..8ea02284907cb801fd68dc38ddac623a9e16c4e9 GIT binary patch literal 307416 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%0A4cu(C942lkY~M@n)~VhWX2M8~PZ)(Rk3IjVuM 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 bVt)y>wc|UPjSyF6$x5?TA+JJF-uQn33IRa1 literal 0 HcmV?d00001 diff --git a/MikroNUC/20260228/20260228051609-Config.rsc b/MikroNUC/20260228/20260228051609-Config.rsc new file mode 100644 index 0000000..ae65e2d --- /dev/null +++ b/MikroNUC/20260228/20260228051609-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-02-28 05:16:09 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228051900-Binary.backup b/MikroNUC/20260228/20260228051900-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..01254148145cb887f3fb518861afa203b4c5e415 GIT binary patch literal 307416 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∈X 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 a`%9>;9pA}pgt#(GR+_B}c@>KC#{UZ(Q$b(= literal 0 HcmV?d00001 diff --git a/MikroNUC/20260228/20260228051900-Config.rsc b/MikroNUC/20260228/20260228051900-Config.rsc new file mode 100644 index 0000000..e628277 --- /dev/null +++ b/MikroNUC/20260228/20260228051900-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-02-28 05:19:00 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228052001-Binary.backup b/MikroNUC/20260228/20260228052001-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..779f2cc4bf0c4762212794cc539a10f3344fbf16 GIT binary patch literal 307416 zcmeEv2{=_<`}aBn&M{;RrHsi?*k?XRDYFzQQz3LlWXu#vBBV(w8l^%>8Yn6nRT?x< zG#V;O%FuuY!gsB64ymV}r}zIo@B2RA_wQV;z1P|H+I#JL-^1_z-D~fYa%gYS!$K?& z2LOapj3T+AVSd3u6951x0015cK9~`0kr8bbe%qdi0sxP~|DhoU00`oS8%2ill!Zq! z5v~UY2M1+^?b!eT6JSro0B`^W#DP5#3jhuPfJOm;5(5J$aWDW-U;qz9zyNM=aBvV0 z1~h;S7|_55GW~*N`DY%$!Gnsx-Q)#V6B-;5?ib`^6v6TdF=F$4B!!n{EIct>8v}cy z6c|9s!+!7_sPSMxPie$Pcp5Pdm&c3<2p`#&5MCXJ8|la9hB*rl9w7r5g#BpF?4}iBC#RUN63joRw z0I&$a+Xqm=0DuqxfEXCyUlY8xr2v3f0KjqpzzV4EQ0-R$c@ z?E?T_R0dk5Jly6FjV=Iw4TAmR0ay&Tgu-3J;36CVJSPGGTpAaENC0q|Yyg%3fU89S zhynoDiUA-R031b9D8m@oZ5cdDJOF${TM4)Dz_4=20H6U9;P*d>ZlvB!{1v?+^7V$n zqmZZwmt?@=khunA9+~+=y`lV2Zz%swy-E72H%TW(7)>#}cpHJyfbaB1B$6BMOAwB_ z4FesXG_WUX4-Vj!)dvS~;^N}s9T>n@k#E%d7fpDpeJrm z6doS+2AVp5Ke>_GUh)gtZs}n0f35AP|0lIwAXokk7c{SqxZ!1ga>Erl!EAqSs6kXH zGuj|BfEyNO09D|J8lVbq(IGhn(f=C_5cu<-YQP~m1rfdm2=)`keHM>16d+*`#R_8& zTw{Sf5ypI07&kO>D1v^!1KiFIWCr>1m~1Ya=L5q%jCU~D!4C|EYQnY^f4d;Sq6Gn- zukOO&Ch$A_0Ivq@iLmF8&xCtGOn}Gm{|%!&$Cn*q#18P|28DYEhlKkD2ZcfK(mgmh zXd^sd&*0#onXvtVAH4*hO8@{H;W*&+puhkQ_Jb!dK?9&6heYvs6Lc-?Y^`QHdt18L zTIvns4k^Jo{W#v72tSV5cZY$e96pRJ5`_?k4`Xj;@%1RUp`%Rs?f`I{@Bor<91;_B zXE-=H&o;BS8qw7^I4nGf8OVkA#wRp5A_Ni2oGiRPC^?F-4FL#2*oN0i6}GDZ0OYUd zM!|?9xDhZG1r6X~Ph1)t3PfBe05q_nTqcL|qdsWZr&HKRW@I0cC82)dT*8k!VPL0$ zLH>#GBhJE$2ne7GI`Bt4JTffoP|xN^TAXI)h(4k$Cfh$E1R}=(HYYqdg6#|S5`L^l ztgV4PF$e(EVgNuG5V%?xsr?~ngt3nc01hVx01tkFK^F#ZJSqe(7C{LRh$J#RasZd( z9UkiE)rY=M10G6)?-57#fye)0AN0@rKs)|nAI#7Dz_EYd z2Mx^<`?b$dPR$Gnf-VQT4vx?*z%@tcW8tlo1~6q2I(3*vKu3W`^D~H{U<;Ew0P{yc zfTtG5`PU8baslA4H=yl_3jjcI1ep+YqbL~w z_*x|o07?M>=w_f#K`8@(8Y}R-;1&QVRRBz_`0|1&T^n^43@M3f* z1HPwr2LOje0N^29`@;YD!Tbuv&*ktd{NWcY05J371Pc8l%)nqK8VmsLxi&x3!<)i% zOciEg{214b5`-+c=JOl(R}MRB(XS4hZ*u{k00A73?061l30LH_;O#!$K_pX9FR`dG?!TH{cc-0B*vyI#dinpGk1{$#CHaPbmD%9nrQL(Y74XwiwYiAJMiS(Y71WwjI%) zF`}(IqOCKcJz+#!YeajLkfvE2!HwXCM~863qJ(ziEM#P$?s^K_(A0<8&>R;Ew?mY* zK-lgb92{f`+kJzBgB)QSQX_0(yMJ(SFhJObuwdwzXQTjdM%feBV4zF7fCeBL1Hc9h z0BIP3@lU`2)J68E)x? zi#`;)|351Mp&-U~4m67@z=tsv*2aBX}JM3g8t8D8Xnm;0{TcuUZE|$&gR-{M%)U{$DFo z89u8Q#0@tPvYvmxa54Wp;bQ+Y3M;e3FO@?p_IY~Rq} zpx}tGA^9%&+vO|r&y(+eNO`4wgTuo@f`=Ug>+g^)YD6T%!PxrG6R*gBMt$W%*ozG! zLIQ%BoFVPy{2dZTkCZS(EdOgItNBsetOJ0O_tKUC$26Q;p1ksN9d@Z0u8b^fFV6<|+Pg;}#2T;KrE z5Qp;yjKagCoe(&S0umySiV`sJqOb+oTQr}P;FC2lqvx}qE42Cb6b+yW)ADg}p#>K( z9fB-{hFBOk)Q=f}#QoCg3BPoD^uK(10wlddnVd+D5x*)l#8!C;g$37Mz@9in#0?SH zQh?8A@HvwCXg-;Z$3TG$)7g;n7m!(enx4;R$-yndq!vu$@z-E39~u${?~;Ix6MSGz z3Z4XhAonB%1T!XJZ}iA76XB2rvNQ+?_VF7g+#nkTKX7dzB;4RU1wP+CJP3XX1x{9h zoT5l%I0508$-?{sy~DWSaAFF-XaGO%{H0*+4(y4Lvw*W>Aej%VT(C;V*A7Sw3Ff~5 zJd_w718IFe?-M2D^#Gnv-@(CXK-xkB$MXvfgsvF!84+RJ&><={Rd`k?oS`<{XQOaC zS5WFPdMN;olz#VI>FN3$z{pxC=UXpg(+LAkio&+-U$n z&{$Hm*;?<+mz#|%bQLxA<9rsR-sx8~yrPm;UGMRVRCOAq4gf*Majfl|qwnSS=R0Iv zqpgkAfch=M>l>$qoU+V`(>C-FV6Ev!)LKK{zx`ojhQbSSWe^XDU^-r5*5B| z_{I%uT5tl@fQCRe&O4+tA{F|QY|>WkBd0#fnq{duz37ExdF77k9{DG4HV9-B<)zj( zbw-=g)T-Rn^N%M;!qMRD{rp3NXS-OyYQtaMELcSwzFFT4NCXZD`*lDuCuEXUmiIrS zx!Emv%>gF7-pz-Sbh}SX@!QtZD%5YOY-q;Rv*a?A3ZY!dZc{R-fK@PTkZ-Ylj+ zq==yU88Mm6A>MeXCJEQDJSZ~6)bo{+ukw5v6!OzD%44(?OddZeZit#o!hgB(N*Vw# zlud_(2J`#^_)Z3Xo(feMuAc&Xq9ULBhn54Ul#Lm-`~j4<(9ED3zNxMAT?vR@Aw=F1EncHb64$-=b-uqU38fJEkL{t_Nr=+0545&)D* z2q;ayOXQ#DlmyVg8iho#;6yr1NCXR(FT}Ng1;9cb- ziJ=L$L&^qKVyF#w8fwG+pr)z;fHPPb=r`1s@Z2`sM#W_NLDgY%Ljw;8OB>qoAVS>Z zB%G1}Rc!}UQy{4JqzkvhRg|y|fkuZA9Kl_g!f8TqJPpEq;J?d-r61^f9t+!0mzF~P z1cK_zP#YTR1>sy@NInP;1NN>5KwHF~mN&nGNNMq(V$VHB9r2= zKoi3P*r{@Z1yd$DqpxXas@*!1G&}8L~se4MVtr-pH_*J&r*VFh`LD^j3kFmBCGU>Y8S5U9>l1(RH_t zS7#zpqImt}8Oa}|P$&@*fH1%Hv!fAtfuEHeIw2GcVGN=KH%rLNd@mk?I-)9Y#Y)3H zz7-O5%?Oo1AP77&bj>8fh_C;NAtazQM_xEe1YioprziJF3V{O#K+E6+c< zHD$4N(|z7mk>im%iW_3GR5M~bPtM4}J-&Z*sU$;`8#mKa?Tpf=f^(g^55nV?Ms0UX z@(o&`MVxhh_JvmWz~+$iOJvS}L48Pibih((J~2N+`QDxEb2d#ni@JA^KH1_HuC4Vh zHcmXh_ux#s*lAS`-T{$bduGu#X4Px91m0E{o4V-6z^&s79HpxsdRfHt?>l>IB+P3I zPMQ%POV+;m6o2pZ`uWpKR9bCyvqK&eunixNDZaN8pDlKvW2T8$NnB3arK37%_=rXh z8)1GIdy@Yw_Fx+4P+afWo#wsGX;M+SwDp+D9T!9mh9)hnGNQQR$2)whe;6qJ8=16& zGvwvOdmAh>9UKe0pB%yVL`UOtCMbWIH7W6eLFv7#1Ks6n^KYCA%v>7&a+_X(Y)Ny- zp1rs1Qnqhiw=txtKziJ{&H01ud(Xud*5sVu<$-^9FSXgJJC)r#J+H2q_k_i}e<#Rn z{d7HsyYH#84aNpfrGIjI@>up zI+;1mFe6f^M1+V~m=O#JKR{YHu}A{;8j^r16e2Cjp0lEpT+!W2PtBREb@MH6WTcb$ z4UkWxFgNcwIWa_W~rR(ns?ow@4tMu;cQ01`-NtsL+a!}ua0=h zJi15hvALTUXN+28mhM4O>5b_8hXNQg%OLxuq^1z=~&aQ8?zF%iG5UbUn);d>A zb#9J#hpn}9+~kysZu!iuqo-n8_cH4JB#Grm73bNd+n6uQzLpu=Qfu#g)O`Daa_q$= znfGTrzb*Szf5rB<79myBBmM8#*%nOjx+s;(2Kv)T=1SA2q9FZH&=y8ZB3N?sEfe}f4c+!dsysJ-Wja6s$Xa_Ol z&vo2V`UY6d)^t`^&S+^4YLV{kEtTsKRocM#19Ib&1lm|dL_ricNfad_B8EW?x6nxB zP#cB9E<${f2}9ozRI;*fczB4hkx?)^EaaPH2r(Vr3!O|B?!{)pTq*3E9ltXxn6KCn zp%o$K@Y2<=QxFD1+e6tyN+t{)CNzNbOUDR6OyDupu~dYNNQmMWCeJ`6_XnU+h?uB| zPrM`wh2TU*VFUfOg&y99`OYx;5H#&w$PL}Cep{D?_h0Cp7~@oM_!hUnEK@Xd%>#Ff zRUP(ruHJ{sD@sJv4c+bx&g|Kv|FAIQ@O8tPQy%1f2u{)af=r)~c>2=Gn9X97kFN5M zBy|86$760;&r7Sjp1hPEX!vxwR3%aw9bQ0rhm#Pa)f*p7Kh|ACv1su1^e6QRJ#F1?o3x}R=x1o# zRqox`QhV~ys_^6Q0&}+4eZF@#(R8=iHV8qXLmh^oi&%W-9nv?yJspwq+tdB_bVk2D z-Tw!k?khHD(-9(t$KbK46ds4iW>8opHj~a~)96$hi@~JOX)FqnMq|)O3<`}wppmI0 z9-B@eaS#@jNMSPg*!)ManvczY6r%;$oXw-KI0%)Z%*q8H*S-5w-Zsd-_?$>tvNr z)*KtRu$bP9UU$2u!CI_Qd|I35vTMuw3MV<`Zesb()fQonwTxdkIp1Q7){{fV@jFK8 zRgBAj<*9liD+>{4+`ES?ggKRu|ZH8TYjySw&tom1e# zUFRpioL_Lt+xpAx%PN?u_%>U@0zd2HPi+KXAC~g|P`ZP4%aOIcucbWW9Z6y`KDsB~ zd^js&7NlOD{#d&4J0;~q)$Mhj(f2-Yb@Rb6-z}daN{BGntDfq>T~+*Xf99EouZ*he z+&inn*M$|+%^!=zd_qT@>fcxN;K+vujq*2~WR|b7zO%LWq~Rplg0w=N6`xyoyT79C zE_nVV;CPbKE|W(S9HKW;?t5d~R;(=8fi@_S>3*1Y6&q&S5vsi>e|LLUfv?>5c~>^b z8RK)$TK0>Mrj_q}PR!|`w?5=_O1^s&WtwAwgr8>qf#q>eki}v$jO9Hr}CldZ!`ZpozZVI|83^~ zH8cN;)5sJ88DWu#WEz*nV6*9L3X9A`I5ZZ8gfIv^8YH+7I)h8)QkYZ{mq;TsI2;m_ z&14W5bS{U<$7w(EuESMjG{UbN|8kgynCp-6J_yc6{|XHPVI^9K9fWLY)Hem_Id&?* z!NeuVZz(rCSlyY+_6-V#lbX0;>Q07ch8nOM4dG2hp!!#o;};zC6@86^C{4JFb7(|Z zIG3Y7n;X6)IMn}_s?)2L24_H6wwh2EG7^^IAuOA!`cqi;eRWz*Fa`tR7z~7CFt9ND z4u+kFFzhsvfX)%XFbvl6!pIm0E7HqH;IKJ%1WiO;;M2zZR8j;TL>ulSA+P%9@)|lA zMt;msrN)O~bOJ&o5{L+mL~~b?A~GNZ6Mp@#kMFO%a&up7PH5T1x7QU`_4uP^KMOJy zD+|=|jQi+eaNPasT zRRq+f_C{F)B~P_ebMAPJ$@6OzBk5Mo$@rY-e8V|;j#d6=+dlzcU%?hG^41Np!3iHK zZgreaJJXa%vyS-q2W<9(QuY1=hc$1bO!nstvZ`n7TI&^B7-iX9Kkg{LUu#D1S^dkU zF4z*8ob@`55((_;&PGXEw3&zIvBDi@3-*URt*u^iL#qZn4RAGj<|iff=-_#c_&JY6 z_Z=9_pj96nXgc1r-M}hw%?oqTvvvLJWn2bmta+JYZ z(>*Ynd*sgX=F85!fw^3)uWztL=_$kc%#4~yon1Q&ME75BXWT8Q+r2|V2Tjo{GR=7T zxi!-zWsLRxljNS|w;4Mg(cjJe=r9?AFX%0XctYqwhQQZvpiBA~;%Uqm>$S|C| z_*X#^6!?WrteCvS2ze4zk#Pb9H~NQSB^V-;;r}u6+QV1!XTpU5jesD;ksKKvArR=p z9N9l-s0rvl&O1cId536mbOIU$R>*OcsG}~`;f_}ynkN<6aZ9Jh?(m$I%%+3t_ILvh zzW(;=-8W70+dov5*T1VNx*tQ+m7Qesm~rKd@t9)o{byr$<*?09M840TGHK(drr_#! zMfEiNw5HbZ>&nF&YgwGSxE#@UDawn|G^d^!kbk>MA?Cw#wba_@bFawySmWm2NLFy3 zeugx#JRoyWahLMhxv7->dAw_(K6M(rqS~ENmF1niX<-&! z#7jJAQs&-T0Ozi#2?#>-bFpFATTxw(1D+^7tnwVfue1CrH#(kjwj+7tarfggix zdc!PUEFZOxSERR$n8|lkbZ>DYLm0eSk~n)lJBLs^5!X@rdIh~H$4(+?2dPM3^u+9JES$m z0Gy||gyU@=+Rh&vw~5*^chjh@iLvACmCjsmx0qOc-pt!H-_o*s`^$N&vgWAGb3QPw zKb&n;G>40CnQv}rG1jj5t+tI@FIIJP?L_ODbK;LRo{Kv9#b@-h>+=#-rP=pivC8gy zyBNM+a77n~)n=R;H7WnS-PUnp)1@4HI^Gy1NPoquU!kc}^m+G#lV(;quXy%w=Y?JG zk70N>{s2w?z$=cxs*-SaD;fnB)Gm{%`iP1(+s>5?t8mlj?>@3(ij;2+J`fqYVeLBV z(eqLww->K(*&nPHuzxYD;$ij5P|0^bva2OC!!+iavz_a zCwIcafAB@4Jx_LS)%GLpN+((uZ(P@CJJ3K`oIP46eOwi@dE)8d93O2B&z6Sq5{AAi zQxcB0uk=Z(-8MJ8sC4^^)q` zX{Oz!areJ8`<2*O#~WoQ6x6USLoTl$G$557-Vjp~l5%9)m?~4hsTPaI=P5VFnkc?weXdM9(9b7I?+y+Vr7-3UVfEks|34C{e*6F5 z{{OfC|Ly<(EB^m$I>)6kNNffRA@VqMCX+zo5(#V)fk>n?*=!aNEXa;upxbyzgeJ>1oU(y0aYQ)-$Yzo&%F1_rBE*A zO5ZE63LW_n=)e65D;p9&DI*~;4mqrMJwtxocxC6A>WmL>Z&pi`F+Jv5FV8aA-I>akRB9Is>8VOIG+mk5I^8UA z%Hf(^1vhHcE{sK|jC??72fpg7%(o00W=$vjzSwAN!kNr7| z*vQ)~{qANFenUe*L9c(@9yG$>d0gbIKb1A7{=hxk?2fDTcWmR7P^YdXZRn|8eLSaw`T2?9i@vO{DpRO2Cl_*=n3ho`;spZ2sN{Z_DlRl&YSAQFMe zp;F0o9-V-Y2_!n3Mxygb3@(#QA|eD5iNqjrNlXHr%|?hs29?WW(AY#Ko5AH#X(R#% z;YXk!ScNE9}SNk(`a3X?^q(1<^O=Ea8eFFo_p@T)WHl!1eZ zQ#dn}=f@4;d{f{ROtPB{3B|8F@YU=qqxkpDvXlJRXW1DH59?o=X7>!%cN>rdv@k6F zV4B^AZ+XODoMxwuXbCvPal-@qMxeqOcSHmcP>Fh9cl!&m{`Hi*f82=wsz`LUqa5?) z!-g;DqF|5RGal`VZpuE1VY(_`vN`df(u88T+T!D0znzV1#`eprXBOKoA?msIm$t8K z(CiJZ*I{n${NSG09yF$O_2l|Qk9*;L{@xX<_sKY}wsz@06)~&g zs{Mf``}y>{Ws*d-yhljf(Pw2t%_95*@jCG;BNG^IBOKop#na3a_!a=1%PRM~a2{Op|JHp!wx$%ndxpN@9v> z{Kwd3#GY-H^HXE>JJa04IG?HEUfO$mcp`>zjM4e}eRI~PCi!*$+4Q^L=07y4`rqlW zew+Vq^Z&1z|5r#yWOE5@7Q*5&I7A+UOF)PW28qYw5(yLng~%qch#U^WX0kY30-H+b zQb+^_i%wz?C}a+cMdMNUknTrbcNo$Mr{(>6EQi#=p8|xxo}yPSWB>DKkOeO`gfEoE z#T^;==1B%Ah_Muzf**rHRRMsbHb(p1g>Qd^@68H?4oP_i(a6J~EV z+rYxiz>H`{v$Q5zQmm|~(f}X_u`N(&Wp) zF)q{mGwLaE?b;&&h4mlXGgiOGD(<@>_s;U*-JHr3Z=8`0OK*Q7zg%Y8vVBtxwbgKR z=@Po$hx&CJC8lqAp`EZt*-SqB-fIb)vpTEWMXyX-RVHDvf9CP-Q~f2*?!B%H?yYe= zpO$sjg6x;jMjNx$we7?Kg{D5+8EwZDWyM%|((Bd)wcXryi!*KFxy;2L?=g4l<22Vy zDGsR7dH?X3ad(T_jJTG?!KXdUY8NW!#=o>=o@g1M^iF%yzG2OT_`v~G@$>f9aSo%; zK6pdvu{o~Q7ErmyC$10$yPW?TDB#d;B(hw+A{WJZn5cjS+QcB zXZN0snj$V)yP6?gacAzQS2cQLw%P8leb03 z+%t3WR73rvQKlU{ucelH-80M9Uovb6zu|!EDvcj=-zzSx_nGC!({T}V2pW^|Dl4X} z#~juqIc}QD2rO-U{d~){mAKrATPtue-YXL=_DrApqK|!dK>#jqX}HV2gon4dYc=8x zDF^CzKX`fSb!Ez-Te?;SX3BX_9gcXMd~a`cqFHCjMGL=<<69@JyM}+hPgQce&*U+i zwapnhb6PfKzxpU~^vKP&a3B8vE%scMEX{j3D5Kw5QEzOJEFCHKzRyJeHdYj^#u@{;nfS!~6+NuVJ z16CfYHdWhhoibxoy3W+kSvu~hSN5oJlcefbKAXNbJz9Ecsh@?UA7$&C;K9r|2a~)9 zpDix#c)O_0d;9W%!(}_qsP#QLFMXpKdGYjPFLo_0cMbCC=Iw^1VztYRu72Dmw^eDu zB-eC9SLK7z{xzOhcl+s2*O%m?=jfdav+Tkc)GY6F-(1`E%Ix*~+~60hb|rb=5gi?W z-D0lD99iDh8)9kA(q)O$v{DT}pUU(7~ z#m(+yGpb9Xwkk$iOU<&}7-{CyRYDs_T^UERzxVd0nU*`@VQ6GuY7WamyZSEYwEf|& zb|RkEtxpWvNc_D+`7U?`BHhk5g%^8mg?82EE!`M5?p>F z1{HI4?XG>7Lnei8i`k+Xa>bejX3QVeBQ+;y(2=#s`*up0_(U zA0KnRI{T_<&*O;`7Oe4Dm+Moq^ORmv;^p!M)er6K(xRnEvS5>+-V&tWQRPT-_U$9N zIybGl{N>ye(%izPT#d%qR_;?R-xU1IIn#*|ROYEoE=t{U4{N-lgI>*@)!pg1;(ptA zH<z%k5ppZado;1&$Bi+P%(`EcNVJrv1lz zk4wi#L@m+Fi;ch?4%<~U;geBdaF&dS?y|t11(W75?j;%Z+ZMIt9CTMLIQG7TLYh^t zVUfFdZsAeZq3v<)kJC>-^8tzJk0mk|)_p8NR%losc0OfpMC&!E9<5!@b1EoIFQyvp z5j$GgW|)tB`Y39q^iH8rOEsp((VE-uy-2Nl+k2}QW|j&4><3nD2l^B@yvWG!)|zN@ z;gJbDZ;!jJmF=vOXFS9^#qRp%%cHw`!rEK_(bblk=-$?g2(*1t|>GEHC zOC%vYI+;x6^4Mf90bz3JG&+OBq7tZ7GKGUczJpCCaEVkdLLm~#BsLRaQK=**lS|@K zxFkVo>qkgxmnB{nxD4Rm*Z8z)lggmRm{`LkqknkvRc#MS4@WAD{1urb~8 z_B}7sdTh)F)G_514q9jC^fQyau1rieb*O4PNthNo=+^RirR)2NUHazYTccx@a^HPE zB*%;zMG{-VI-YEnrWjSX-Rq6c%ciSjZIRRO66E#GgLV5?Mm>CgNjukL+k=YHt_Kb& zoS3HXpCsr0rNn%EN?5kvz#(dC|NYXP8`UPqRbMLI&TL*mxeaj0T%E7(}EFEhHZ zjJr{;P zT94nd_+5$0z9(`nlrQT~Ea{ckcUx6?s8(h(Mfw1xa9yov+`iSX<))8~*u}oB8o9Am z?xFs5w6~UrqEV2itizTUlWtflP{eYN;CGCEJnR^^XKYDXaw`4thEZ67F zxpue)w=b_%RBIv=j}|{^cw$R+viHvkgeil+ImsulS*jm9nM$Giaw+li8Lz^ccj0|`g|-iWW!n#C&tJv zkK}6Zr0t&&EUqkPtuvRSr1$*e_5<#SqyFx$H6a_jbb_Cz6OOlV9YXc(A1If$C3Ah# z1MgkYGwz=MsLNh-RMqA1d0XO4vgcpdI+!qe^qtS-P~*ADy`P_`%<#E*(`yX;SG7fN z&`mm1-*F}FW~f%2M%TrLm9uOE%N#ar8# zUKqdpjL)-%FH>T7 zZ)qKWREl&mEFei#%j4FVH93#3ciy^_%#P`QrOJJO>kanS{Bbu;r^qd%=Im*^XrT38@wnx-B#>nUo_ji@3`M7XV)(Wv(~KP1^YJi#i&V+iDYk| zQ!JLRc%t&)T)EV!qrrq_1sYctj$3X0ZueN7V;=JDRaqix;g|O{DE1mon07=mOvcis zT6!!&GdAAKx#J_dMD3B2bLKSb6Ov~TO|n>v`+9l3-Jv_j6$UnFyH@+8q;9>>PG#}x z6V%;|lka+^b$r5}S34XXv7~HI<@2v zz2{$&6`LB91}|xfvzAwTV%AoSA)aqOCyB8*7hp0ybE`~RLS^cKmS;zc%`R*BS!Bva z-7&g$)y?B!Z1efVC}0xNxlZa(OpT&wWyF`1P^C8}OVIf%XIYrGeU$e-REV^Q?m2~5 zFS%`n9+lU6^%3d5TY`I{+^)stM}o?GMwQw3E!Jn{%-I>w?UJ$jaA6&mxMtQf$JIKk zk6m6IQfK6~{e7GD^DBenHlZ{n40N33&#XG1CG+6e9<$iRL5C7Mxo2(su-7L`xmcKcVeSg_MMmKO_tfo_r{=`&7ErMCN>3&&3vw;3mwywsw4S@2Mcnd;4WI>q+9IO*P-XMDa%<_q)5z zCofW4r`nu9xmmp6s+vwzlFVwA`D^DPE*nQP!}g%XZ0sCxt5!L3S~@C%I%ucFxy^g6 z1GxI9>Xf!;`;+g9zik{>FdHQ{&i9d~v+Gmdm(<-$eA^uC!f$sIOs-9sTzbiL)|u^D zD@nzTF=v<-$`TUd>T`mhKF*h+J>$_^&9A4>F0J#Ld(a_p)XBGYhfc7$L!co!WD6=ozrKT!{KJU;GE;c3A#yNI zyuv1I4X;%rWYgtcg`J|GM3;xGdA*(8a?woL`(;sj?ejIt`k06ZC^gYOO3e|ya89kL z5xwzdNq*6`FACg=bM>BjydZmBm=#A{$(5LEH(j>QC-)&|a| zebqTycSWW&6m7eHW>Pv@6x|;2^4+wRtUK?HT)L5#SpLasmD%iv{!M#ii$k1>W3S&S z4Y59cL9T9ndiSzzJIhxbnc*Kg>9Xa7ki#FmCu?PNM$gDpHF{WL{?2Nu_fl~krp=p} zU&$0I%A<4VK3-&ybuHumj`8&v`abu!nt$F`Sd7jTEnhW#nS@vSmBd@;GE64Dmzc7G-BBHSI>arYB6Rn> zS4SrwR#?a`)!6tpw9nVe8^4ag3^TV{J9pEG*DBYEyRW*-NYpqO^$euH_I?;+tYY6G zGRJev+zmGpXDL3}e-B$BGgEAb?#d;b7o;s!NEdOaDeAQ-)GaZ$aF$fh@+hM2#a-T( z_+T;xzdPr1T3E8{v7&of;`a4hIx;jab8gRnwsqRnaU2t3*z?J$MaitncdTcL;dQIu z`WG!%Oe+2oU8ue%?y`r<`7%bN$P+IjZM>3Li1@bYM;S9q|14AZZ8E=2X2d%RhGtX$ zZ#S8*(1-~AN#bxg3?h@j zVIo8di9}|T`O)`BuI$gFFU^W#ZDCEOT9{K9R04(nl*}K(%>Py7mH8h=UNW6-O);Ze z5zNdjeja&=Pfk2;eIxSyk2?HYBJao%{bl4WdRiQeYqjXTkGXp~&SyY5a?-9ak%Mbh z7ltP&Z8|=A&r;pzzHjRs-YOX_Um~yZ;*yG*;i*?WP~}fA6g??>w=D33$k8}&e=&(G1M&~Bo8r!Ixb}KQ0Got8 zl3k4sU3y=nJ5W}#Ro1>gaKGxM7kwPhF)r7MtRoHk%{D%h<2c1Gyt3Q$UQmTKHK5{+ z&C2Z>Cyv>Ea7;IdsaDPHH!x2cs2i_d;gC^9JezJft znUy$q?m%^%Yevnk)bxgqj&S)Ky-(7VJkry~);Se9{YvCDW}S|Iuz7p<-ecC4!F4_- zKROro{*NMW&a=fq*RQu7Q$NXgeOHwhWPI~nSJ##gqT^rH9eMRWF+RmQ{doSe1L_x- zwpmqmsG98c>-1Q;a`o)U9anlMn9`^2UESq*e`lu=I@Rs*ygTHed*vG!;p0`0SKVod zyC66H_;q64OIc~%M{^wpp0s#BzmQP9GsCL6#kJWu&(-F7Dw}6&e9TkD`*tAFS7Xx+ z<%?Ze=8UdW5AQf+hQytHrf{Z$w)o~v?58fG%f>7DeFfWc4&0q_H##wFwRN3aiuA|W zEBKN)g-|0+mRH*ss@q2QH|>3#+wl($n2xgDYpl<>^s=RS)qC%$`4c(~bG}?{I^4bZ z;fjHGQ$mjJn$c&}SjhkRj-O31`a|UXZ8E=22KB$*WWGjT7Lh{X(Afx;&0tWdG%l4w zrxLhi3X@79kjQj|Nh2c!CY?>7vbY?C&gBxA6dH?4C$h;*8i^<<;Qz>#{dwdi5iPCF zsg`C|bSrCwf{Ms;YP#{8?Dx4|xwI!6*axn`ncB zgF_X5+{3C}em{CtK^6w&&ocZM6X4JQJpH9QzXSm>B=P?U@aJZcJnW6vm+MYUHNLYU z-~Yn9N93dSB`?qJle?@>v43@0`cUTJw15vvz6G=DVwFc1RFXI5_HMTwH>qREdz;8ZPPyZJ z9~<7QQ?pezljxk5i%E&Uuq6lF$$gRb;;b9onVkys7zY z=@~Z3_m9_jd7QI!&Pl2%XFUonE_}E>tIqME+mp(b)|{8K%J1Ij+S+6B=5#_|npVZ- z)Z3TKi3?viUtGRXb#E$CKh+ACd`CKEm)(qY0k~p`9mg)x_uQ)9_54(PLEKTx3Xg)! z%3%72L_(X-eaoD?Bqe#tna@bsyV#oN*5=3b%%{yFwOwtUDl^S=E)u!0r9hvPw`xUg znFZ-Sw$=Eq3ZuybwC_Oi?yW&~)IQs7ercx+Cp6w^f)vHuJ%ZgI9egP}f3~`DM+)zZ zNcC-xY2$+n?qDy1CMpN;gmr-S--TV+)Cm<7+wA6eYupC`Dvw3!atx>dGONhteLC?gS ziG7T_j?E&K57e)HG}yj3Vow0G{^oVwf~A~{HSe4+*K9?^?~Yn{WPwCCSa*7f%fSm3 zdjr~x0(UYV#k{=Pl%H0%s*h(W5uGylbqb0H6H0)e$k?L zE@7j!+55c>Z(ofU@08XZ7qO-POQY4b!2&z)56--<@=nu?0kHO6TcTYc&E|7?Yk53i`Ib{{4zy|~fNwf$2oQpPKg%l0hwZNap(XFNqx;_hEf zB=nv$qJF&L(Ajh}PDQ$YiO~n?UF9bfNgH>rPA{WHw@whbtavhaZ;Y4eGG|e4{^jHg ziE6eN@?t`kZS=W)s`Tia{Kbh@AJq1(y0=r&;c6>h)?@MB<4*H+u8$H^Yf;RR0z3Au zVTf<&KSzwTMzXl965#equi*NU4S zpF@)MOn9#*RAr^l$2WH?oO(Nl)AAyIsfeRZ?u;EuWr%UVqeGn(fi=Y1H za{81!g;S)hwTY`9jJ-5zrAX*DG3DJ)VR?TkBOSw^U8NQ>93{@ zL@Gigk_l8ILLPqA$?)R{mLr~UpKV8wLu6pBUrZ8j78n-J4dpNchjx&VMB6$Ky)_df zInu@cWqxrC7uDRV@zlBea*4@XXO@(6_GhavPjC6^vc@l+$)Fo6QG=DkwBnRYGsV~K zwLW!hbjw7;^t-$84U=~n1*POp*fr+Dk=Jrg9#JNN(b;xclchIUN8;Wq*s-} zw8xRnezjvQ5>49k_nC*Uqv!L$A9@CVr(!+@&DyXZjUKRxWG7; z-{qI58un#8me{``TE7r0~M>b;j-59?1~yXNUFx!~ZJ zn|JG|y{KGZ(Hx~@mT4r@-*c+DA>qFC@#K=gmseEndsP!_lCCy3P&uj{C;LpDsRJ{u z6E!B6AuqMEj|{4ubD?!RFOUOQ((3i6dj22w-UUpO>?#ku*^im7o@vc!GUnf?BA?kgfAtE*cA>_z$Ymz@=HALpKX z&bjBFbMCpn`gOm5>0iJ2i;sNp*_VIox4z-?UYdIL(%M&j^c%nXW8Z)0+uyc&J^jS{ zKj(YDZ))oYzoGfg%ln`Dzu)@Y)LSlo!+ZZz?VCUH@t=6?kAL7x_WkOkXFoRc?4N$k zcTWA}o8SMj_D_D+6Q{o78&CY<*M04~zy1IHy|4Sl)+Y~t>2<&872NRO8jS(`2Wt8 zcnVNBH92*%IXg3RvfgU0`m58e6MoB|2wKx8S5MBY&CX6tH)m#Ma1>+mgn!bXo@kw1 zo1Ul#6V3X`)yY}D2&zoc+ucwzb82$t)P++MGqV>KX3w6b3p!m@9m&J?UAlqX5>~~h zWRzDf4~fM|A;i#w4+$Z<-R^idiPyq*@CIl=LWuue9R+>)l~-Q*W%c_z_T%~D9~DCUT_Hq62(ci9I3v){%auuGPMT5wpH%i>5MapcNM#?2?Z?-H_&SWQ*Q<8kp#J|X_5Yh-)B0@n z$6N5n=cqr92{H6iRfwU(Z&gp;hK7dmHG;3V<7*6GL*nJ5qJoRJTEUv%YiH9!92Hae zdIVpu!q*c5w=M8z)cO5tynGa2ufx}@5PFu(=M-MlN?shrixc=7E_wUQ|6|W4&GKF* zbg1%|Gn>>f@%1q1>mhs{6yoRu-QH?DY!b;o zE`(@pG`r(zkZc9XcoGwmP5_qw!YoRkcM2iiDHbQu(E%YU74h;Rysro`bakH)M~_s8 z&tATC{>qJK7Z=WsP}`4+myaH9w!`Ip~ys!1)af=ynbX0q&;Ha0Sm7Co4jH2$F_xO{o|_AGkI#Q=f^B_Z8V^ ziX292!0d9k7EHXYuh@Q5Y{(~T&ADLfXkV!VrqqGO@W#{q039?19_WPac98TJdB7Io zp8AVCXp5}-iN79<8AyOz$k{`t$g5j%#}A`g8u&?bqm~BQW2G|%nFhR#D2$?|3+i`F z&le{#LukDMx_B6L!IBlEaOlZ6&93;J-~tx}4Grx>!EF?LP5pL#>i9EPuRnG1`qi7) zj@NJ3>juWh@-Vi;G{dBa-EJJWL8}1l?FtzD|8}uB`H&DF+9wXb28AyWRAg?W$^L))}Dwjpgdq>iORiLd=TANif=D9}z=`_kDy&ZQuTn zh(jNG<&{?sd_)}jK4OlShbo6ZB8DmlG1NmJp~Yc9#qZ~eL$?Vns3i`Hm&q|h6<o1DM$wSYH5A7F!@JChg=-Ic5`bXa?4!k5P2VW8uw7oA6);@r>A1!t(&xu3wiV!r6 z{TR#Z0QUpWi9_FaKrlFm)gKtbJ{Nu>gfCRR9~93WzA9dN&sFiUZ@(&j{Ex1RUq5rr zK=I&nqJlnXsQb{-pmCbQ;DCS6%91Wo3= zdJbWze}gRaZwN#E8^TbxIpjQlY#*NU3{+?a4yv&p#xR9OC6R)Q$^(-ZYg08-^SPC$ zP0d4uAk^50K|eTiu{Lw!ME%`nqTlsnR|wVOqu274UXAV!J;+jIKf1#oXyjouGI63_ zo0&XSpSRr}zG_-{h`M!KIN-K$aOPrd>V&O|xz=OtuX?apb=v6_Br>?_1ASGeZLgrL z!BrpZt9r^#4p>81?Vp@Os0yM7wlFy-ZKq(U!8M26ng=H@)+Q#f>)38LTU|ffXs)em z*{@e($bP-bUZNFxandj>gp+tl4DAOX58X~{=lsmS=4TsNsN7QfOsPY<2q<&A-An_> zHQg(e4}8!ob{qJ-pcIlJspv&2o~!JW5N1-ztOstVwWXkWK#HS>XY05T7zv(^#jjbTbL}XjK!c8XA`%_JDYw@ZO-&c^hO0F{(mFOZQj!yCU#ItsT!;A`^~j= zt^8?y1^;8!K7bYLAaVd=r34CSV|4V@?|IK${@<&xuM4vAu$$G^!gdxUdR=%Li-5x4 zGwL_~i_~v-aT`4>#MAp1CqG-f{4pU`X)D;I?-qUk(}#rk;fI9yk%xr%(T9Ziv4;dS zQt{J5h|dy2{45Pwh|d;6yczpc!GQ+ul-_~wcb-%=6cTPs5R!-^2!RuSUc zD?)rng*0sOT@}`zzq=yD_f&-V-ii?aQ$>h>ToK~?DnfjJMTn1Ag!qAq5TB?B@sBD( z{7^-Re^L?RpH_tU;ffGHQW4@uD?4@HD8&C#5#q-yLj124A%5;bA%3DF z#7|a)_!ku+e*QrreySqGFFq*5Pghup`PV{-|4j(t3nBia5aN({Sv)9Srrr7C0Wl;d zK?PIzn#R`*zD{80ds2v@gQxIo7GLv19D4LPG0o5yoJJ{Zxv|xLmk>jf#HkBH488V@ z5Qj!9LYx(1Xg?_{=TQGV=n#MjgKdIn$b!Pj#_480QK*UwbMkoeh(7<%RX_%p%RHok5HiXHs=0KSl1 z0-Qf25YU2{6$G>(8`cmMn<4Q<`1;%U`aAggkPt&(VEN`DA%-3x74Qh&z8Z}`28@wK z;0YmyTBEAn%RuuLd|k!YaUqT#45Mx@Bgs*NV*3_+(e`~2zdU>)+!PD25aQYaaTK-` zle6oY{fm>#L(EUiTg+#l;i|u0uA-U#G;-Cxa<1C{H=L_TcoAz6SGn9l?BcKwu@f;C zu^2HMu^llW`0;_bmvwtt^f!C4s{Bn_toE0(6)gmR!#S&Dy?SshPPYA|1%`Re*|^gQ zqD;nXGTR7b(rX9zwTSguAz;W%X2z4amxa+f{jb&Fm*|3bA)q{nC!uUB{pvNa^JCG* zCizfBh?hufI8qTKhZiU1D=#Bf^>Yta#K^;olW%?H%!&LVNQTGRF zk4tqAABNZB(BZ>}2iN_c#~yzW{r(8*{s`*sN8Rsv?D2!B`#q06en9p67iO?&b0cW= z+Cc&=!d(0J)nH-f`eF6^2_eKcs^19j{kZxK!@>8e-`G*;-+#Uz?Jz>dD&o+8TM%Nr zA`XdHZEj3d#G#kwhQwq=9NPYat*`@K39vr?ejyJ1!Da)Pt2KFb)VfPq!=lmUcb|YwR$_sHK8AWo5@JEo# zx%GCu>bK>3kX?$>>}Iz$FRRWUK<4W;z+A>}x4EH@4}cBREdTIJX`0F2H~J~TIH_S| zxB;dCVP00to&xIEl)U)feuy11sFj1cXEK;8CxgW@63`Ew>3?KlF*o%kz~-lZtQ_7w zPW^qN^>u)f2q-rZuowEUuxP6T{I~ev{{{9HR3JcMeK-P%^(tikJ8}r3049i6JqSu0 z&pO?;biCLR8)$1iXh8w2NIb+JyB1=6P5kki`&f z!*hh4G^`C67YTpb6T&|>#Ct+)2M@mn8$4|6Pm z#y9Q;92o(_>d5Xem?rz@L^?b0GW}?Z2tivj!tZ3S$A$6El-WL!u1gSj5XuVxW3|(7aZJA zc5!m7nY14eqAn_5_5E-ElV|?(2Y>0~L!a~Q$A0H0-ubVBKYiD~`=OJ|KPtcL#+U!& z@ujc%(;xWof!S{#z46RH|H*p>FBbUwFf4D?hAkG4d43p zZ|VN&w|&!p`u#V5)6#ET`Y%8K8yA)?{^^tRU;8y@j(>6c)xY<9zx2<3?RREwuYdi= ze^LO6;Q^P~w()`u0_}l;Tzn*;K<$w512aX_H$QAE~e8boL_HRbN z{m7sF*$+SVdk?(+D`yYl#m0dXum9wqeDGU-;4Q!Z7aQOE>*v1iqhB_EL{DNGWKds? z3m!59AN>D0EDuS!gzKB~nnET%N&zZGXDK_#tPC9B4DCk^W2kXuMxdtr3gBHNHmU*_8;PZ zxXy4+?5TaiK*Mr$9~yd1Gl;sijrMk@*4;=}Ypv$i`w!tc`Tf!`eplFR$GsLvd%qAz z-@F)ZCh?VzcMW}SYR+aa>$*8!$KTdd!ZdZAjBK0WPY|ESpQ#p z_VU%6=Pq1cxPHEN=~``})dJ*%?7KF;&u#o|4`?4Re?Ha5u^t-8hxh-91zWIB=~IFH zfZKTW;17OU8$XzD{DYrr<8O8+^Z~c=w?FXre%x*SQ^om%ZsVhm{Gr}4)8{UYKZ2ci zkj8Dq?KEk}qSZNs>*0g{zl`ICJ_LmbaYT=?IHN7L-fDv@UM&P7dk(=-4Cyxi09*xg z*mjFUh*!d51@FZXBEE7{h(kx_J{Y!zIP|L42SeC90D1>^epQ6% z-xFXnbO22RLdfS1A3JjR*jzhq`fatLLI91tCFkB3uSWQ}GJoW-DiGZ6E+tL-_l2+> zpm_cX9I^JvxiG;4>9H#B;f>m4KI4bkg*ZVg&eKb4H#UOkd^^R%BZueK;w12!8wxrZ zMvdWHvaq#U3!|3Y-UyOF0_GPzy+x(nEH>M3_vFfmY{iY|&1iVr^0eQU#rDS6gG}!v zY5b;6aJ#GUGpu%+Py6lKX%D@6BUJX-tpae=7*NM{3KS)rwt}|5BPUZHW*TG)zp~gs zHwmN68D0ae0Sq)#=xkuw`6Gvq-J0w6vcBdE@TGAtX$C6=|4)F5FZ zF%-O@c^|H73K)}BU3`Sb47yvF+kO&-(Yo}Oqgv@_Ia*dA$OiSZlr)#4XYcwUQbP}6 zv=*cJWz)ZG$m8aZ;{ys3_zeaczfmj?^7DD*6WK8O8ihGzin2tYkUW2f5mD8}l^KcV zr1*@89MseB4D8;DZVJ4j8F`(RO+|1{X&OOrJ81T@Ky}sdZrz&e`biqdWl#TlUeeSL zd-n*Kfy;p9jm*nCa@kv1@#f_+16cszdFspbZK2Qz&=x)rYVnyx3d~ecv3b-6fO+ow z4mv+3@j;M#W0*jtDISyFSduoE>va!wIoFD%6%uR2?){~y=rP5^Q{dra<7im=trkyG zm8zma;-a}MPP0TBZX({L8ekVLESqtZ1yPnZ6sKy|b9j&Xsyd=m)tx_b_%2W?NpnZW zQ7uT4I8m~2UD99Rkn`8CU%f7wPs+&u&XL2%a(xf%vN*>~P{rA!872JmQ_j2ua~#XF z7(`^8KsYO_FHNSI%l-=EszRyg8^Dz-C9UplKm!^i7SIfulXxuIcwtb&js74`m6m4j zO0~xrABvd@cxJG)@YNDy{?6T7RoK^JNn<}vnk8&xdH@^Up~br(;LpaLZac_=qZr?j z!x9WR2(yJXp2pC(tcUArG*Tm(+8o5@P+~QoQ^DPc8HI_>8O%6hHaVXpkPqC?coxU) z@wFgpZpdD@9s8}uPLRr8(rye_+39eT9^Xvb5H#bSy9|=(;chV126Wj=gQStKp9YES z`f0iyC$0ReYkr!_G-=ilN>>zY`9VlYi!*y4Ko3xTz(R!G0y8VXAbS*KRC%~+t6R;7 z>yog9Jhk1@zVqROT8VwwRbnSxEw=StA0aLF`A>d?v{)$JaBF;Zxe9v_D(nPw*zY`G zSH7edL78|uNaU?KS{n>2U?&63hK9NoBxx8&E7BYGFhHZ=sRqt&_)!$JA-!2Qwhg16 zeSQrq=hPr>!PvDg{UkGh%PI=5NWFAaCutoprO!t# zr>UuYQ&)N&ei`*TvO1lAc|FK_2?lWlt%YlH_|{xIh-CFjud^Z>vd)?^jRg&Pb?*)p zRk#RJK-mqOn+)S{l@2aEf%+p-wY8KbD=YJ|*ae_2_QCMvnnY7*+)uKVJ2Gge0ahzT zzcg~5-YNluR*6oTL<{Xvk-Agp&XL1&3E@Ci4K8Sec5{*^1bM6KPU_u>N_r!noS=2v zm4Uaa`F5!QNG4BT_t>4}?j{F!_q3vSnsdzivHZlx-5_#iMX5>zx>63RON-a!*|^tk z$tcD;oF#q}+c9##1uc1XNg}{J3fgili94FbWSS*mv_2=F(?h?SE<`QGV9$-Il@99w zbP~xO(eF{&BwuAaUQbmqC?JLba&)K==r%5gXBzvDMQOtSH- z|M+i_Y=jX4vawPw8(&-6AY|qCqsP=DD$!MFcKt`#5TJJE#@~EB=)_xr%#vO(Us#ak z^YFLlR^;=Ms-Sc?r5;Z}J)S$J+P)rOndBZ+!z6#z>xB+$Kq*#C4~~j-ZhSn6(=oEy zjwQXE4WSjRUEPj?M0)fZWMW&o5GHAMy~mP{*lfW(GlE$fr?=ZR7Cq;c?nXU6ru!hF z@Kmt#wBPOpOIe&i4@X746EX$Kg1tect)8ZqV^$E6rFn@e(}V3FxtD$ps?pkaiD^ zq{cg4w+iV$-HpUggNA1spiqWYKMk7@IXs*&j^uVAlK_oSJd)Fk^rM!tlZ2UE-N7Dm zJxIuMGA0-O%|NETB#^;vznQgnWVR8eGLC{=8^fL&qc?x>Hx1yM9!0j7fejAtu_7D%xb+p zIdgJqqFz7I^!@26e`0dNpPX!+3T98%>ub|%tFz6uQ!|rm^-2F^{gm&|v}R76IAPG7 zv!uA3f_;nox2~ZT9@@{Oq%x~dzjZEL_ZWBhcJdobnx`0&q)}?w)7ArR-jP*@OLYy7gGq_qH6K=&Nb96$ z>i3mkTdrvPqT+)RGp8~zrjDe-hpisI)>10dKfHtmd5-jmELCkoaV2%F zNki>a8BbL$6g5&{mv#0-!(N^)u=7z3D3gmfB00pifenxJ)7lo~s9dR?_F8`C^X^N1 zO6JQ<##|ORllGdtMHU6!3%`~teaHq4^p8_TkmXjiyTxhIK36XWB)2#?zFf7E(Ps`mt-{CwA=PC~GYzejM}AQ7|BVeL+FdO^a__Mql0?J&O7w!>^A?q#)R(*E?wAR-j9XH~8Kh$X4& za6JA@11tgOZ-*(wy5Zshk4u^R7)cJNh7umflv&y|T3%b05p$m@&2g78Vqf&$d+cbE zHlYnYjf22u(>l|ZN*VmOM>_J!X&75gQOE8TqR29t8Je&Za>L_);u<>wPxIl zviT~{)Oe zslOgHhQ}n<$f}7_UW;WzYQQkak&%&kII}T1Wk>^)l1sbs*GxjgFG@vxa(GM@1O<)q zo%kLZnV$ic=Z$+w5!lGc$dSWj`uOl6ZTfhNHhr9nw{}LY z)^L(0Na9pQ($njoxJ@H#X4FT%M)pB&?@OT(yL9*sI zgYoTfE!5%bw8c~*>}(LJ0zlmcchW!)2T+cl^j-50ZPTeM~Pcsox1|%GtsG z3El=+v#mB|YshE^Me>|&5~{Mi(}1jj5{7dNA1zyHNWYNp{g0?>Bh;iiAflj zG%uz-4nKdTslhcz^WN+1RRmjN{WXlOuM_O{*QP2)QM;BR!DlCu$!(1-W_L~Y_(WTA`F-zIoBXm z^2y_M&xLm%4q9c(Qm{&;lWPFjGUMz)`GHvgs(LV0%YHaIR&}SqsZPce$6wo&q$=#%-tL8jzZOR?7h~7Iim0ws|og7Kcm%0)=JiM;V~t%*FMHIaoyWG3r%UDe}l%j}Cra3>wHb5)K*d_b$$MMNe3pz2UFe(*K< z-BgaRS+Sgxx&mIZvaNO1IsG@CE2K41&mwB?bTi5NHL9MCyE{p^zLCk{=7^lE*Jo;z z^~n>wjguVc{x0o0In8b!)KfwwH3DZ;3s%UT*<6uUuoX6g8fb8o>5<#P;vd4QqV#M( zYNd1P6%H8kQ0b9&V!+M3+kVvDS$*7O_QJ+m!{|Y z9+VM9Id`4z1wnS+9t^%jo`oGGyeJCQ18h#tY`7L*Jhssq&cqdn#^{V}z`U^$riv-o zd=rYC^N#L`td1P!s0G*fsz5Sklwyx$upQJFzvSi?+U;|!Etz*E2U5!Hj0z{I66E$Tm@jd zV(qk-cUAgPb0bbtZ$!CB(=2F_mlWYu=5v=u$lvLW$QPwYi|>6m(2$myn+Vsy$kL|#-ZsZR6CJyc>3>k~u`Nxqum za~QhNNzTX9R|lGjpIjk;D!xQht4qiUBvmO5F%G}5f|1Tw>4)| z^YCL|LrQ&GqYP&_8KkOCi)i9@a^0 z0WY%h(?I; zdJkr(C7sB`;S9xJRKu2JJWG@L#DJ(c>1uR-3(0J}{N!s7vCh_z^A78WDuqLS$yLd5 zyuG9lQ8n`uXAJ5pSBpD)Y>p|Ui-5}}7tu$Ow67UM&i(b3<-AeV(8I6`v^1(3KPfCU zH3*3Y{p@vlY8=Yz?-D`(1AAjRtGje*uD>BDg##NhVBa@HdbkQCHRk&PNw;JW=fG4> zpt;m6mQEFEVBmTRJk3)qJ#$$&=H;@IgZal!GkR|KkR{|(pi7DY%E3@Vp8XS?C(g1) z`e?MDBH8%2<+mFXt-&)v6x%-+mt&u76NqOI*L#Uip=AglTkAzl{Nc))SUykj&c(&% zUgQRmhK)%q8TEi9HyDA6e^wg<8*=E{UrNg9Eed=P>7CckL--IEHrV_!dH6qd*2o`9-Sr zC~;jBZ_7)^J2DHCpfxr&Mt`&ee=CgE$K=S!a&&`E0dI%xwp>N1r;1-+4chVcD9>@2 z$|z1cetS#>n87eOuY8oV#xnRi$1=zY1F!e4flwU#D)LQ!@1K8^e3Ll&-4~dROipeC zuoo7e!EE@gdo&xmZNa?5GD6SIoYrm_TJ;v?`b>o<_hu@5hEM3u$#Zd($t>S84}7PASwsW6C!Ai##J zwwzy2iKXz17(w0#Yo^bjlGVOH{y*(nE zeuSCor7*>(ayw|Z$xn4jw%|d{WD@YY-BNzkpt%vt8Y;+^g9q|b27XHpYY$hFHphbP zIO&YFf^pm_GJfv-nVT2KHnL9p7*(xtKWd?B~rLNl>1+a&HUds&3>Q-F_lHbMpvZ+Se4Nd@+cE#Bbk-)j0-Z zvG?ZfVFS11*(Q@Grl(BDgTrV%asnS~SPMn&W zoSs`)xH$D}Yhq*V>Fbk=C%P9G*3Uh4;`6sQt_IWZo;?}u#NBOojJm0_8-9kCY7_PP z)QPEysrqdF#1sbMP0vhE*QchZXHf5$yqUtW6B3iBK}4sDOz=KE^|eQ*$+HHQUr*v* z7jvtTt2@52kpzAVT~F0@2e1R^QP-MqBJIRIx#8nLORNM5h#p2loL$Of*h=LvD3toa zpGQXkY@E=MOxkIsWAY-PNTuIy$J=O%>XOBWJte73!%nZA`B4z}()P|+Kh7CZ=?&F8 zX=M(Ipy(8l$j@dbCa0%QO`fWs% zZE2wurv7R>km*imHEySvbeD`%2bXS_=`&%rv83u01n&*y3ppFNI{O1Dr zz%O-?F6kWK&}RJ^VRviVGJ3qVkvoIrR=wc2+X!{Gb^UHQ7Iwq6ov}Dsr+P;YA3LUZ zc_s|#%l;WoDEQb8n zo{9I;HA+Ru7me97eteid$7Z>zI4@GY)C!_3%&=zXF~IH9!FW1BHr9!H%`v9xfUGFR z8cRXcIuk~IVl=yai+F#Yb59hc3xkFCR{ssx2bU^Q{&;gIdFPD~2&u^yp^@ZQSd&rA zTbX`TcP>-m&0ZdrGYBVYc`@K&OUj4lsA8A*bX8b z-%B^c?ntpcUEkHFmzJKCPX#;uV5S>*>~`DP3CTuUA1hCbvciNAvgIzHb` zqRwfKh0hBqZCL7ofIP9e-RH9K}Tg0$rDxU8L)&yJubo@D`X2C83)qizzU zFwlcpD5ftz-(7^^uKYyM!&tDw-`0HEY{+!AZhzMo?ID)tN6a!e9?PvX`{=_W3BNq3ag}S zZ#wc%=>%mN)%w9z$Kq~W@zSL=AXc1_}p*rEz(eNE#QD~ zQ53DbC&prEcwvuWf|CIQ-+Ix4*aMfCP`yS-ri=Is+S>O>E z+6INF*-p3wN2r;nBs2N|_AX!W7~Uc~ekxs2%0UDSYNRnOgEI0~TTCsKh%K$+E52$5 zAr^FwIfb#^*^ygLQwe9}#MG&rwM(n)=G?(}sFZk;36QY}_|m}X;!7LI`lb`E=%=zS zCr+WbtYxJ;@R;3e^MZFS<`x&MpW2QQMz9tcNd;}6j{C|8DQ#W9ti=P9rOi%b z-zitj80iuMs)s@t*} zi9x>mYV~@s73xfAYI;#+btyZ{(b)oTO$Yj znO@j#VOHJs;rdm0Z!`=V?rWRtNXL-*S0xdSpJPgKhJP{0_(dPC&!%sc@+fEg%yySp)o}Fz6euQlwPQDeN ztMyd_a(2T<&aWW39(3D&6Qk{Wwb*NCVYlr zKt)a$7n1$ z?yGZGmabD8^e{qPf^P6qN>XDdqKw#z3GBnOJ{Jsi~ycjW|#9*VS=beJIeWaRE6;FZ;=QKt`M5 z8<;y5)`KWp%3LaN3|Axu!3$1R=e0hyR{j>aQc;_l42*PeM1aFA5q#6x)4mIheRw@b zcq9&sNj3A!qz&p}t7(|h0*hRkDi<2mCL2fPtjYFaQBkpP3TuLtRo#H{P*>~73{h3x zs)%|1YeXfzWWdhyGNRowb|MXA%1=vo_=Qsxdnrl$O>OOP9RZM%d!3`scVyA7| z=2NZuu8Q6lp{=E9u9O^p{*DQhWb!Y*_tJotO>gdbZ!_5O<~*F3AYU^5zB6xH(CHsl zR^0&&-WgHlN-1_YKMdq+3%1k_#v75hZb@~gfQg_lkn?(wd2(gtj*>TIUh9)LIg=u3 zuHJ~2L7XV*E^s^#u<{bro0kQdN){1_wR>(-t=itaD}~J2Zk>0*8@c};lxVUY8SzkV zDY$p+@T94Jym@&mzasDz759c6ZqmZ+i0C#XSJsCa&HE&Eb<$Fokx1O~`E6y?h1Qwd z(Hf1w@KDKq7`&*=zPDtxSbz>pkg&q7iubz?J!fQ}(3vRa4fw{Bt%5sJ{AMDYh8& z+A${NfXM5w&cO1<48hQ%QZ+d|AC9CqTnwvLS^s{{|U#+%<(hTB-vG<^8qW!!q}SIg?5schS_JvL>~k zs@S3;{FQm7=;hnf%uGuWxvmS#70X>y&Y652Rsx`OGlf~!MaXk+%h;J5P{2-=E`Ux9 zE!g^+akZ>8MQjVzyg4`rt)7m%;*PnKG1z~~%5GL@g=DJ%DY6KQ(xxt?++t(#QA6Nb z3v!0(+*+YL*nGzhgqXE88x2I0LZ6~UFdyTqZ)`n!s_VFttN6lQMxF9jWpN(5OR@Vn zuNLIq^l1h9?X_^V9X2^YH%Ot30r&c?HLvLzci(Dq3Y1+tF6liPr+iBnIXa7#v2vKY+MP`K z7Vg$9@f+sPEYqlFCZK%kP}nkG|E%FAnXy7COfI8nukE`m+}B4RX#j^@!yuxtSm^#4 z50 zkK%h#Oh-b!LS7wPuO9+3oDXi-@J&&0VVK5Kk{e|SY$cMUK&1su+R?{7=P0v*M#@5k zK82RXl~>REl~&te+3+rC<+xA%?d#3XBmY`fN}xm@DNcc_ZZAsn%pl9i2LUKyhWk(` z-$R(4Ny1=_Vxvk0j!VFp7q!xRQsqrS1fSlkQNySgHt%tSL%S zr}eYEFwC*g#<0Scd9C|&FvkUMuZFrM=aQ&}OF`Q~w4QA=Zpo@Hh?g1P-8LatZ$DM69DxVW?G<*aImhqI zY6zoW1<}GEtbZ4+Z8?>fG-?y1hmgN8>W_PUU%cu@Ds#lC&EP}8(}>W3)tgjsFKSaD zD&8s^hGQPo6f=zXwbNeLM?45oenWa;%cYZD+s~y!8Vg&Ek``CgCXDx$x&S01=Q3-@ z>ml?b3Q1KKQtSc{&sW$iNKN>dO6y{^GpR!rj7yfiuPQ-;n_sV*E5jE|0a142kuRXF zpNd#6Maa!lRoQo#fG%TAmcw=VghS(#%&%4nH_l`mYGPm7Wh1Z8_m79WycD&9C{wDi z2GQv8*OCB-z56NJl%UJKAi?JN4qt#vJ)06dC}%+WHbx7y8Ij{2hY-_~3CY}71{eE5 zWgwirT}~?bOS!zN3h*)M)lReCMu4)Ti1~-de`BW`T*c)$nxd;bF}cmf|ZBnrO5*bf0(R373>&PK7mYbTCKDy4kMsQ^bD1rg(qkhv^S2>Trivz#++tJZp8O8 zlzwEl1FUzLERARliZ(u)S-vIJ6`4HS!`?Cg;jB?SMHnBN`YKD7jfUir$pYn76{wkTo&wMpb=O&#qN^ zZtMs~%h&89Ps>wvNByGRkGeROXQeJro@7d-7y(_HMamN9rXgr0RBH1OE{c-ydG)uQql3#stM~Ogg?K zPPVv?tAgPi_U@RSSLdjuG zk@t%kPlxo7%Y=Klk2W#jF;7RDln4QLULC)O;-~wE-pndZVjsDJA8>HQ6tmdmJUh{Vczg_KPtsLgnCR0XhPSluVTq>wT*f{XcsHhRCg_rIubu=cuJyh>`Gs5p9+-k2k zhwA+ju2SOQBK1UVZqyyeTK4zt4vEn9TWvYwhrIR2wigp8nRy-@^qlmiBM#L0gqxbfy7iizRN2f4e$$BhVfK1v zwiVcQ3m?1}?k-rzI07I2?e#b0z@i7Js;%&bQMI0@C@zvCCnp4`NKZ?dGVkT>XKE&p zQCHtTe+!YpaG@a5i%L(@b@fJLJ|DH1uIOcfuCDYt{E~=nT2CJLV?fs0F3-u8UdIVZ zCA6U#ukP`PxiVdNuj5w$;V?pglk5r9ACao9r7T%lagBi71z;}rp>XUriKZwpI>}b_ zG#a-ija%(*2^h4hh|`&B-5wRGJB1uqdfDV@6{>IMkd89Ub{w2f&tPteXNfh=3Z+i=Z8E|oH@{y0OhFwtAKmNJ=K^W7Ike#Z{(wb zxBQqXq%@mCO44uTkJ#%C?F12-#uTONlF#$v-IzTwPibWuvnS{EW~wneHP0(qV|GF> zI=Z!CZ+YU(E%IklOSRM03CNHRJ))l|Q14L8g-hO-<8?B}X^cujkM!Q5bok{#*?4_J?*el!QtJF}I&9Iwx_z&9{^>ZOtw`2oQW z!y}>)DW=ZcJ{`6vSVHpzXHimy_uTHPbjxlCmbn6cCv`!JWzzy9-%N3Wau6#k!go5; zJNjK%QdQEzC0DZa0H{)P6euniSJgA;K#FEqVBC5-+$c@CmIOg<&APhzC)gx zI(6zq{Z!tOy4!6m&7@t^mv$K=%e_^n>s6?($LZ*EHaV-J8ZyICD_qET?Gof>&-Zpq4ljehUYDoRnVNWo4FHP=+3zq0~u261w8p~8u>dh zECG=0B&u};1m_2JnmDeOCL@c+q<5ThW|_o>)>5UQbuE%w;;{2v$+LnPQm=(XU@XW< zhjNJe{>FYfe-%#I*f|k5@__L`>1L{4L^qkZk`t-FvW>f9W=t+^#JzS4nT6v`2Q!W{ zltgNgh1C7z4!@JrH|LbyWtv$`t1}}^+kD5kzez4&tZ5X8QvS|;no^A%Y3^wvP_N-O zq`EG-;KL|Sm(sKsBxkSiYU(Fx-yQ3i5FSZLW#JpDo%YUNF)^sF9jBb8n;U)@(Lu*@ zY7UXVwHbH1xEOX+(kH=ahxwOHNmwE8@W69M!g#W=i{jH@RBm6)Kz@ zw{=Ptm+Lx>fGwBL2f!BSG6A6xM2Ar{il^NeIo6Tog8s^{ z;W+Wz4R{Bjj#2Px?z&L!ZUQE=@kZdcf~2+<2JKd3_<87SefY$xup;j`9zmUb%uY3c zg0NB-sF`t$=`bf-lqcT3R?UocXFl~-d-OEIoxHj)N zC*n(jZk&d=Z2YKHhFN1`%wpNuLI(J|VGt()Zi~R;spxliH@lk6bUlvYbS*9sm@!qd-<5Ok% zQy^*nlz2=H=KG1>UF>o@k58TKz2jEpFQ*8tnt}gvnhMKAN^{EBv0J3%ZaU2Kd;Y{~ z8IDL$?n(LBMKvmFz&XeVU1sy*u=ieC{>|);N$=TP_1f&p6R?M<-ORx0a8|axh#c>@ zOfy^t(~FE+ZD*sOJ6U_w8B)=i3OsZ~ox4Fm!n(T;$>;zwr`71CxhT1a`l)XR`wB4( z;2!i3(|AGuSoAZbtTVxE#_*wy8hWkFsRsGQU)fQB9T*!1;AYr?zES0V<0OC4rg=)2 z*zupFh}Io@nl{B#hkaycMRksEuf(#0p%&MvwYV2Kkrf)1RzNd`OH4(%aqc!pxq?tW z8FCsT^jeMKoJdtWje#?(lW*zx!Q#B`>Q>160*r$S5`YZtW-qJz_i_e*WuMm$DP%Ue z#PP@zSRtqhkeO?IccQ7_3b?z=g!P(SJ~e8zB&bBqj?#o6?unlHFubK`p2I7_Hn!dD z3sa61se?F45ayI_CyG4B0i|ciK#}UU%JN{S{$x>BQ7-E7x$byud}1M0SxpC5E!hHS z>vgWxK8-Z@R;5_8-Pq8!T)Dh3P}u9=WajE<-ASJl$h|Bk_(B#h3&o&3UbaMEt}gpZ zO})K!iJErSKjO{e9NL?+caQKIAbZ@cjUyaYSl6h`IK)L|@X@=M{My3=K+&+8&b1^r z%92)l&9$D$id$TsoOt*?+37B`c8kBzBJDm3w)I6)Y{OwVY#c_RUvpif&X^re8ys&bHh48_ljCprCCzy8sUXzj2XJ`tmhfJ>qGC4`WTpNT@R4Yo$ET%UcKdm zusBqQ#aQ99cw(AGw4t49fw^<843sj~7*o*Ay-qp?eVjC? zqWnM<>xMMAMP;PS^D(Iysz)ZhLM={tC#(IU*Ic~G7Cyybj&`l+ZHcmaTnUh5MNzEQ zea&sk#gjMsx=Lrj`j*ERhrQ+HRYIc~7Y<_jod6H%C3cQhkU1k#?G{m?yHnUue;R}+ zS(xju8@I#e4xf!P!(dFPSFRBjp8<0G8X5|NRJOvkwSceDRB7$mhFLnwNEa`;4Wiwosu?laMGAw(^w&;%e5sK>KR9?~ju5zndypUm_Ar=H-1LMXWy-It z*DC&~Ew=Hj;G>|{^I~L&x;N2v_wxAgQRJu#!)&f)PVIDla*3Emtc1!hhPtf64dQ)k zy@U?|H)I{2O0}CPlyV*+4>QL5o**5SL>jmn)v@Uly4k3en>T0X z@>5ujFGsDRffa6ur(W2=P_AHU45^9AH|No{pOBZO5rg;);Mn`qy!c~=ZGM!8vm0_f z=4iFASylrEG%km$8tO595R)aN5z@#ZPa@pF z;xgL+yc@N`rB96ur-KnJ1Iqe4K;?593_ETeL|KHayTmY!F^$FP=0VTqgs77LowZjv%*^`WcOFzQyX)7crr z*~b`HNU4kfl!WA+1!-7NyOiZpLFV9N?}IXn*RG4+U+Kz4CXzPJ4Qk-Zc7yyGz~c+8 z7J_It0?p(dKkDH))jQ?VX4uuqZkafavs%)?8gm@SZZP!)H zQ6>9Zmra~C^-8S3?ORj_3avckcZHC5oeUf7H_YzMq`j7d*w7bqn;lC-Qy@!Er9)8Q zoYQD|sUo}B33X7woX48!;8Cm13{+scqnC0!uREbB_zXe@lT&fhx*;V2&|43L>QAc# z40mCBJB}RFUykF=RJOy-z_D2vl^Zq@X9eN~NO|qHkmOws>%fF`BUtq#q%l5TRlkpq zNUbefzrk)}&W)Db%|Yatp9UzvMgwM32(Cte1^|nkOD@CS^5m4>g({AklZ6!{&mC@y zrTj67MR1%h4RDJM*w-3^7_kG{gcwSJhKfodSdCjdqZ;jGgGU%S*7tJs4x%br2ZMGR zG;&L8Zp?Yu%;uLy4+bh|v`idMv7-$XVKQ~m2UVDMy}75}oVUWq!i}H8PU4Ea=?xE}d1 z_;e6pW1#rG<7UIhb-+O+eJo&kE*?Zq1C|Xnv-i;XZeo)@rLvPg&Uz^Cn4_GeLm45X zZJY1!g-Ou5esyV3z}G-wVyETwu`3{%{Ae{L~nW45Nt3xS{Y zlE6u_p=a^jVqs&UwJVd5%UZ{4r>m+V*zp?D!)+TX{;|B&z#Tlv9tY~G`8|rzDT3CL zp0jnZ_;n%}Y;E^An&uOioj+CbQa9AM%E$}(=EG)CqpQ!?cnm2EGwX3T1aPc%JAPfG5V~r;vkzF& z`vA-EyUcVvPt{~Qx$yGo`%1y10gD`m`?sQGxIA!&ta=Txi zSmg7#lGuzNUdM2K9$A&`Lm&kSy6D3+$3`3rYA(D`U-y1@SPi?8r4CmR7m+o{OL|&c z3>`nID;_LpInjW1IFCDh$xAC}CV`*g?!_eTjM z+pQqceQQgOA|9razUGvB_#GwCxC7UL47NU!Ve&0rM8JJvBJNFIRD!iJu68+IKg$=T z(JObU$`vSEu2kth$zH73&jZv~;XZA8NFVHKa29~hc}MFS#)7>OR>s|^fUp8d%_1N3 znDipYhNz|kS}X6=?xnSq?pt%#prbae0JBgImv*+yY?NZuiCNMPc838JiBMiJ1T@)J zbwbI!>DB05>MA$mv`3o;klJax=wH$)?)Z~)>fxgYrF5>UX+&8@`qPN<$D-ERNZQJ{ z*p3!)o;7B;OT>P=2QCv#ESzj;oc@>zrc%nyQ&dAN5Chc^eCz;n^2XNQWeAD@%Sgto zmi%#tl7rrMZx@Y)ZnsT2XgX$oK|XybR3vXe&38JO4apX(7|~SDF`+j0Tj=f^IfJvZ~|xMA@RdVFBK5{Rx$B*TME2UeHUwC z0qXcWG75qgu4d){t}u?!O|I!{Z7fa_H&6uIwBYyX0yVYB)_75?#altr_IE~M-;QJw z)Uc4V#8*YEdSGY8&`d6^Z0o->Wa>OM9MVNdG%CI> z*4BLCCKb8oNxBkjr$mJ;P54&zsBnNpg&irSxsPO&Y$J@?mqwD%Yn+OwMN6wK=WmDE z)rjx^l~w027;m6K=FZXg1&W#lP%AlpyB(A!GEr($F?Lj2s(4@IMA_xesIyr^M={6^*=uz{4V#lak^$K! z5n{eo+^Py*^Rp~SBF9>g3)Y4{!CBIcDVm$E>WVtQXNZ^=K%sGYi&G3ciihe_`5Fpo zDGTk>eFQ6JjVfp>rZBbD2aCxys$rpWdVPUh;6WIpJO63T?fkcbfs{0DYUei^usg8k zwS$I^Suw8>okDD(A-DxXvvXFw9J+k|NSmWQ#C>=R17-3Hgl$Up)?k|oIzAp zUvG2q;*D$PRmw~5uEYQ!{iIbm-Pq?C#+yNM}~{orFEL=1ggSj%S(P-KmhE$D;il1ads%05v;9=K0A z4?b3Rq}C!Mww0FJFi2ujcTK2QgGG5g|2B$FC%nT)*W&T0Y6cgk8A1m2Uel7=ZIAhd zfb?pftEdwr@eA(`=hu=t`H{A=WxXVqC7VX8?oQRzSeE(9+-7j4*I5mmMZZ*#sk2Ia zkpToB#e*wBVACh%#HO5{oSmLMadL8Y2H1Cn@O3|G#hr6O+wVKvgbVKT?GQ053c4AE z8NcNuX5C4f2R%t=yIG;BCZg3$^t_SPqZ||9l zdE?IHtryb1f$n+|j29*lBfK2%9lN!%Tpb>H;q6bn^Z7f=%UZQ@Y%hNaf;_6clMHb{H zWg<}eLY`t7pWLWZznCGes5&UR&7aF6;#Hs^F41qN`VwxIa&|AIjL-xZ=-9STgv*kQ z-qt1VBWXyF&gwd=ji>KY@uZ3@g3lMbagLOy+7$a4+zzuqg%DE5g|)EI|IuM=PU1wq zD82U%zW}Gf3+&V4^l8I-yGEr(Xl+$V@pFsZVi<+z{44;=EoFYkO~9-z`^|Q2^2e&V z*urJ&@)k}X;Fne~^jqR%dW&Dhx2&AF!6tB+2P&WxTMJvBN}*EfjjrWO~mc<7Xc z-0g6cny8(g9I?NrMhe|fMe2r>&&5Uao=AY3dXZ8ikB{LWZlgCe%O4`>K6p=#PE3qW zj82VCkDf5_;zPx`-(i)A(Yt-ykAhV{=_dY8FY2{>>p{1f#alsh;mY|l3)in*U--P6 zS8iUudGY+Uvp23jeg3Ss$KlG_1jOK^)?f$%8r$OOiAjgq7v*qu5i9GYW^xOxi{4@A zfltWl;)tA(QyN{w?q)uAc6N3K!B=;tW1=`6t=8aqoOUYC6e~XYq+5|Ft1jiF22YV( zr_)zzN=lRKR+UO|D%KDawRJ+uQ>HB?)P`?WF-|b*Ef5a<-)iyyPd>^2cRKuknmV^C zLAJU{MG7L&obETuW8b-4)VAw7f!MckBFz+SUGp=(xmnA)(k+!)xB;C50w1~7?bvJ) zT2WxJ%bJH?$8&44fprr0x(Q0I43eB>l5{uKNq~goMv*MZXQA|Pn+n2lgzALqRR*Tx z-)>CQse-Els+GyyWKK)?E!CHEE(?BPCuIb*iNZMz2XcAuu=ZPzl`_QOtAWyNDCDYf zyNDLx(>3IV(Kn$#7&HQ=5yI&|Ko^ zdQ2(k8|TzCugNl>z#9CUZK1)c_plkqw~_lc0&@Jaf_;lU3E9qId%XpVuR>F-y9bW-Sua=Rzu$LvCr` zV`F0~AgdJz9Fi5>4pWL6HyanQ3vamG)@!HLO+=JsRD-S-I@_62b#N5+oGzqP6pc{Q zQnYtWnxiJ~DTPb>?mEIIei zL7yT8t%Yq|&oE{sZjO2ssYBGNj%>jk{pf<9P6C1s%=DvLHw1(%wR$o*;J&m(x|!3W zN=XbA6?NgKRe}w90YxR0MbPC4i*@!qdFeKZ4);Q2=&clEbxU8=dZ2Y8b$15ycfkFD^Ga-3yd-wH2nD?uweWaVtg z)~F03f3;ma_Q@U6t3Yy}gim~Ec1cyv&#?2(lDF;tY!dhsq6aL=c#TlP06ET5Uc5Yl zlkM4ZfNz{ZL>h^5G*c6`j(@v`j9{=Y>Wy2@hm^&c->!9nPMqLwf^j)zHx9YAKMxc0 z53`wz?wsd+mm!z%kZw$))#?id=lYe=0h!aFz$ykRDzEfdDLS;e(gUO+bt$I2T|0}; zg1_i*(up}O^VBkfW^>{i4~naODKH#d2>zh6e5TRnuhIbL`3-2M3$z(Qx&_TW1*4iqi>^FZQZ;!qhck$AdT;+G{ zv9h{@7M41{nFas<&39!+s4rM7sAo$VrD!No?|D&E)h;0D(iSqt?_8m0kYd>uGWJAW zi2MaQy%z};w{z;syN7>sS2EEJOZTRSc5soUBync)(K?Ks&?DIOB&2>b}4x;b_{L?WWCajX_?e-*3swoGz@xH6%;HA-D{CqAko?AJVtmvwZNv6v$%(zX+|e) zdMem4mnaiHRZ2wDoko;(Q?sNs6}<*I9&I_ZC&Eo%MiiLx@OGBAVUS`PV95HL00ERi zk&pB-J?2`*)bgEN4Ud?W^*q8N_lKv1JKEp4*=%KAv2K8tDQK~21hRC9fUW?9gr!AC(I;wh*E&-e*l z_3e}}`oI8@RJyfR4^@EtjrdBhV+GhzpiDsm$KCRB>xt#%G5j|??6^Ebg9U;Et1SzJZIhUuv>IQ#66h z@(p;p=~5|ApK9`?$H!;c9qW2*)xN<-KOUFEekKtwoyoKtG!ay7jz{_JFxwd!aLU#q z4k`7ein(U=*aO#!sRqr6nkb;gVTs%XX|be;or4x~3kQ=R^8%&HmG#>b6h6Uj6vHN@ z@~UTwl*=_L2msv?1rX4-#OO`@3K3o2sJVqn%i~K(p7*@;J`g0aH!nS+eEb0M#cf84x_g*{K6?_lL3O|i|*d61rV{BUJO*I$Ec2DQkz4@Sw2%RH=vg{CSk^E zgYlXtVZ~Htl|y3%?M2Jg0ijAy$olQIH8=Q9JDYp$EQEWP{vTJp_laPqc`NF{a5Mu9 zt)|1mf`C#yKdP9L$oW_*060Ye?$Qj+?%i6Mxmznq^R8{2EVQ9GOfwqGxZS2>&>+>K ziZD&W_=wGkNod(+I+z6Q5(oS_{LJT8FUQTzA~&mqG?t%9`E?l@=GsMHrP(X@7@NSW z$vW71p>39>`&ip7tXGp(pzO~Dq!!93dXF>Y-cs|Y7z~1>SlXy?jJ15*`VcaZMF7-J ztM1g{`+?o;RD`YTA5cZD7!{(>S@xs zVp@x2OR!au!;x`^W481^YP6p>^%M zVpbW=fCI*gUbz%l$_@q#%5G$-mu9s}4lY_d4QtkjtS+?pl1f_rICOQQ-m$(Ql0kQG zr$H?ZoKQl&OT-ja5Zphex&HlNTGQ~Q*64kZv6`n{5ptxt`Ptmdyj(JSl|gf& z2)PfbWIpV5d038nQxnl{qG5N5sgZUc7|X9=nq5nUqq{Y8$9Pw)jTBe0LZ@0$VC6Gx zo4akX2J4sglnGST1*_RDo?62Cf~gcrVW2Xh(#*Q0yVV7qzYC#QEw$rPZIG`fALnBC zO6o8`QD!l$RkK{{w)O_il~{x0rmto|!W5_YqcC#v-0cno(*`eU7LLl^&%NM1n zT8xuGW~2b5GTZPY4Ud9ZWjND40ehp!As1xuK|7dZi%nrgb5tjz0Le0irR?IOqUO@K zL@(|rMnNj4Amft^js_}EC`k?RtBUG@RCVQ|rh6&Mf@I4_&R$Kj<8o3TWaHHfFDQso z7vV;f)S`#<`ZVXhHrs!S^3LfMec%vH5&h+Ec)g`rx;XLg7%=bd#2fx2pd9#WJODjp zy|L5bgczoN=OABk!(Il0g*JCj@xXEHg?@9ZSs&&ILR|F(^SBkys+@YOg`YBasDOaI zv~0P@apEhP($Cjv<|l}^?+|-|t>UQZ9)c~{l`PG?!w}Vo^ythowp=Y4_cFQdbEZNZ z?Lg2xA0Px%+N=8X2(=8;p5fwcFQn3zgoKzSDu`O{IcvThrrP%ym(;~cxE@B0YJFa& zz18;x&8$(Kn3tU(P5t$tQJtKZ?J(MGRHx=;8n)@yk!eY0boRXKPS5Y{xHJ)TKO|a7 zS6u2sZ@dy}0e0W%GZd_inMGJXM)=t1xiD?|NelaxTrvP%$W;UK=>kj%Bym$okI>`@ zSq)3!sGVN+$js!H$1E=++9X#;v!$73I;4MQ=VlZlg9nAa7184BQ(bfl##piyX0*qQ zTGkJ9@vHhF_m!T%oh3e(X6dM&%VD)dd;Y55?4@4ATfR_Vp1rWVaB_J;9kP|M{`g6! zMu$L9N;o%ewuiju0L0=7tSu9I$3z#>pCw_n3qkz9YifZv3<`@EuWfk z-Y2aZ!t-jY@olHj$>md1w$O&3WHps=3HAju5HvPhD5tV*^p!hh%eCWPOMyFkYWdWJ zeUro~Lah>wiP>|@r_P$!fuCd>w)azKmrtEDFW15(uLbyS{QBCx&Z;j^gBDfeCmQ}1R-xuBU8(>c2YX= zDu}DQ5l1etQ_E*8f^-6n997v#Pn%(y#tE?xCg<$(sY%m!+DzhhJ6CnqsoDwK!A|Y} zWA97gqyvEMr>`$^2If+NBB}3t+y6 zMbc4nt-@?cDZanY)0Coa&*coI7s|{#MZ-vELn%F%vn+L-yKassy>SJFMuu+gm$S{x zwEQHfB*>bs0apdjFNWwHN$L_C1V8{`;_kgX$O*+XcFIdZZA_mv(Tfz1f272MxP@m? z=(2W;whw$!J^Ir)9O~#f?wz6%dZ=SxsH0PvzsSu417fTLDBho;Z|LSeIXOWYIy*w$ zN)3Hc725m@C7}5Jt`_F!tcq-VSU4Ei)#z@vge>H-qXTIOHz|2}FY+@Wsxd|icPNlF z6!C%yt;|}AijeFXaMgU*f`-xIh8t{HLA!DCE(0$xwl^uQhHW)^@aBO&Sko}&-mUbY zWvhF%+)M))2?uPPSPh=-lRoq8%AWT@#wea`UM(4Pa8iNA2f@craxYyK;^rMS@bkmQ0^rMG<^wJNpi{ZbPOS<~#^M3k4OYa(> zzXtK6n?CHO54+hz+JNpTO(OO@R_s37upXMHhvw;_d3tD`UYcY-O|qXR*-w+~j|yaY zmVDLeu<}D=VekS+R1WuA$H^~0UErC322?XJP;)?jz>-o5fP|&wrwbKU19gJO$~@pz z?%?i==;tF}h;Henc@L6!8T9~H7BB?DV3d1W*zoZBuqL<|61?%D77TE9w>;z)O;N2T z6k+(Vp5yV0PuCP02QlUhjmIJ2RF1l8aZf}r77K&#L2lmATJ)mX<{CL;*4FcIX}vdU zN13jZKVb?04)!tUU@4bd9JC4rBMpMPsEy&gw=teEk2#=Mi7yt?^s&&7c$yD{gfh8T zdykJiW}mxddDUcMJuK@FZ&N@|_^Ux3ZpN$7mnqQkjk`tJC#7LDXP`kQG(^?#^3%zJ zTWn9~Orzi;w?tiHGT1}8n^B!E8^H=W*#$_rFrCFhI%``6^NzBspBM>w`^txjBA9RN z;32kLY=_fDJnoj*MBi3I5IK!}C~2F$N0qe4O!Xd+WjAdD&VpXEE_pDvOwL7vpP+dyR&Hf!;vG|32Q=>$N$6(WSr$V>@oCL#vLfZP19PRzaIe3?dsmI5MR{ zV>H%Q)Bqmu>y<<9UGR)1_>wVUky)h-t}$u}7D5_^uF;KP#lz@SQamx zH3mHZc4^?^1V+-X1KxAGhC&cJX)-Su3`aN$>IQI%l&U?>rlCazRigZZVe$SUe210D3PnuVG(#4P%CzwKB2{7LJ0IfxTdE5-p`d#+We+ zMg|84IexaWp}HJ8Lr07~EsI3yc^h=t;z{5aXjrLU?u0!=H&##Xa<^0JO6^GmhZ6@a z8)k@IEr4L846Qe!4!wa52VIHF(^9Znw3bD~K_!M&azkl5#|;X1VTm}I?2c+rjGo={ z4Y<}IzP4N@rejYF+(&T$`6-d|GH!pPmd&OysBro!xOlu}F^?$@FoiL#hi2mX;#(-; z;G9$PiXZ)qIMJpM(lH5vb#woA!3UC91gEuJ2BR;EZz;c&99M)~r=W@` z*|`IIR2qi9BLTx9m{MGDYpsmoZ)?EX!LF zZ&KfJo^ls`rB0s2l7Rc(m0`sprHSEgc}cr_L;!=!R-^m0sj6_up+Z4uCBj4x3*%GH zj%eC$7BWM$5SNBvdnK+YQYXWejI~hU7kP*qF+}%q>O(Y2FXj(#*c+cn}OTLpb)&(>NOtTM)RA@oUFB=m5S2CzfvnDSjNpeKvfVB3rPb{ zey@_+r}?9$9M)|tgc$VA@IULDg zh{4A|)D*L6Lr_A{kV)c^=IQ#S#3lRBud|U)*sOC(=n=oU_IzH4YwZr)#D!UAD6InCMtP|n>uejlgkpiDD5S0}-9oZ3H2!yM^Kyl@{ z`GsfvzEceN1_N?nHy;@^FG9io0DdijnhtcCbdM^p4np2ktcjY5^6Dg#mlp$Sn~KGV z2A@(}AgUeCI&yNnrz>v^FGma(ZOtwuJ$eHix6oB74|>K&w}r16y2xYnN=lmdO6_LG z$a^0n!QtTmyG6DoI&avE+K|3TWm4^+Wqa#Cbz(yWgs1*8nk%0>FU18FQAT*>WTu(S zJn}$irqWPvZUSK@t>-j;TSP@&+LbgdzkW~^kw7dMwRFIKeya^H&ZmKclwhbKeN$1w zP*OAJPLPX;Yy#47Hz%ZSp?uZmrgC|T(*j-IfH_l!o}p0|VK0ZUlZ;vLC4oIq zs@%9)?;ZxJOp8Us?P1g%3`lnOmB32_PjP?-yo6wsu%`fv07f=?PFpZE-8N_@&+ZTQ zV%R#a@j{A>(!j_}3FZ@0(9xBGAKwvB?Dq|Q#+V-fr6<0_gCXt+%p8C-#{6K(=J$4C z3U!b@so(`o!tW_!ulY}4>{e(PcqQFn%5!0WVs`fm4Qb57GvB0zZ?{rtcW?{8i)EJv znnxEd;Vz}qhU3hXavI1L7-$O~FY%oM_%g$w{~ZJJU5|T^Ep(57m(Egf=6L`kuj(<68L!a)P*okU2scF3$bA znIohjwf*I04LQ;9r}c#732Cf3Mo7amb2Vg^kmhxGzsd|D%^Q_s3__Z}hty_UmfMyu zl+tY}Jv~<{;s#xbnLynD+}&bZj=Z=9Kv9)lQ7Fe-UYK}FyC``npo+GXKG&XyTW69f zeJ*J``n8=MZQc04&W^TXDFr+w*Tl3elN1o9z2u}iz3HGB7-aHd!UuH=A5<2giVbKD z4CrUJJb(jw&wF2u1NtI1pmi{yUq}<*fNo$#z+hg&$BgSaH#adQ8f_MaSGyA1a(gXr z%h|jw82QW?v3e8gM9fNf@G4QLw69KkThX>q zHR9N5)@+f84TzE`qQU_s%j$>f&$Cq@32hvquO%$sgfyO2M}Ly$x*4~)jhw*G6_!*BB~8kb78Vw;q=kirF@Kw&XO-Jj zUrR{CI~xd*g*i?Z3v--o(q9J|6bPCrN?gr z6uPrTDYQ;6n%GvoXr6Lg8==^9)nYg3MN_nueQy9NajXPlLr5pI zrQ;lE%LZtz?dXJ%x*8z+ni}%@sn_mqc_tBVZgceuAA9P{45Jd@ zq6^kFzx3sAy7iBL^OBGK;H@{m;kxVpdHX$=ZXWpaUvB++^PRJAd%@ltFa4{;mGAze zSI?}k`PK)1e#Q^lpYy;gr$^tMeD`$=-!67O(eRf)`{EOCy#0mm`RDidz5L5Je5B!q zM<000%O3wo-u&mw_rLB}*J{tb?7@-Gf9chKw&U;rY+>*7fBpWK-d)%C^)+MYyXRdGWG?I7cg0`d)R8qm`cE(U?31J8-#P0=Gk>9v z*538=hXxw&dnvi}MK`|Vw{M^O-oHEhl|O#-OFM74`{6ePP0TtmF}3Q%^yVVz-gtbb=UCtInJb2`7)XsTv|n+> zP+{zb!O6o5^T*SX$jr>*q^|G7i8)KK%__?bv(qTvEI&i9{gdx}Xa4Jt-E!HMt;crH z?s;g}w_mV#=dC~g8~y5kee$Wd{Nhu0zUJQdbpO+T?Ek=3FE+P)XM6kDdF$%Ge(pca zo%ftCJ@*U0{`J!@Z5+7cduRUjz?**Zir?J&m8o~X=#Q`3-+AKI8?(=E`^%qyIRBc# zx~IPP*Y_`c?wM~Cn%?{2j{C^Qw;y@(V{cnm{PFu^-Cw%(C4c$3&^NzQx8;TJs&9Dn z7rWl_)8c?^<{HT`kRX-~PczYv1%(^1Ijm%bm}RKlDid{{KF7<%cfI{P&}u zzW&iadc&)J`_IqGj&+{3BC36SOv-_~?&6 zL#|qP!NqlpANizxLEnF$+ZfrlYjft&S4@8MbC-69e(~cQAO2?S^B=sRW2)_I#`dIn z;3Z$V<3DD8d;PCIQrh>!xt`8+?N|SJ?wi+zYQFdDw|@G}o$qe%{p-3bUp_v4_zC0a z`42X|CHBn7bL&1e`Q<12{^V^(URw9N@$CNZ&P#o%VH0m`>h`~JbmBG z&p(-baNR`e(Qm%^3%j2?-S)s!*8b0Y=xgb-{xyI7?5p1R?$@@h|9WV!_FZg9F`|mSn@A$y)wxoaeH-jG-U$--P==>kl*6+$pxtG<9 z{P92R?0W2_e{;!?j@*7$?UN7cZTG%n=l>#~J%7VJAB^4q*#odO>JL74*PBM)9e!ia zyWjYC|8l|Lx|2^kCpOnT@Yv_B`1jX*@Hc-qA2HwC_2effuUh}s$G`foAN#l8y?J*0 zdG@%T&J=l|%tcm3oe|M~5^{^SP}3w`O! z|MbJ7`?8z232W7ZzyJ-5B)zpgSLdr#Bi`M(_5^0oi{`5*q|OIv?1aLG6C zJ@KVmue@#DWAjh`{ZG#Q%%>YJ>$&LB;l0mXSbF%!&izxjbWYz}f8p?VH=NMl|9JOP z$=Lqiwe)}NQ};gSwm+G^``?)}c!e*XUVz3%$`xBu!@FN^Gd>aBnN^>2M*$8S5=fB$P+pPKoX z{WspRQ1kYywzT!W>Z5mMzkJCZzZ?9Ak#F6z@LTJ{m;L1pPj#I4oxgbC#ibWKsJ-FB z@yCazt{rUu$KoXy4gGB2Ctvm0ci;TzOLqNx@8tIH*1q~zAOF*j{1zMWbbsW$clOS{ z^`dWef8!;4e(}v)jZe=W{^gtJZ{4Onb>*EO{@K%?YM$!<<}>%~`Hx?{ulS1J-1D+K ze;#?@%+$l5)dya`=~vNfPyYN^SO0yV89$OdI_LJC^MY;v*#5O2WnS>ze>?a1U!D8X zzxnjj2lvl(zw)fFzU2OU|M{Oj`nBsD<8giRy)SsqVExWkx@byqYW{%-z1U-bF6eE6a9U%qJ1E9Q^C<-OWiPxeDvXm?G3MdVc*dQnjUZe z(c_Q*>-XPzKOH-6x+uiQX> zu>J#I(Zct<@Qd2(_H5qup~s&ZdBM3y(szCHyuI6h@v#Tf@BL2f&GWIpzxQEiL*{*7 zpN-tn;lB3IKK{=7n?J98=s?46>$6|}dc&KZx@F9+`sYXZ@P8s^ZxdU53ZXV-1qY%L*2XH(RBEn-|RD=oSOLakAEk-f9p@4_tdAq zwy*Tzw}14u!r7TaPh50``L(|8SKnH<<*rY>|N850z2>JEe!S(nec#ys(GNEfLKbrA z^vtYX${ANN=HoVoi-3OodmSMJrVjoA&hh6bPM$n@27CUh8hAd|wSAJ@N63~*a$gT+3GYwvL==tUY6rG?Q)cXY(X!uI(BolcW=vW&)sl zqPeVmXxBQ{?tt>^q5N7=ex0xUp0e@{U;CkKr~~!`QGSiL{dJ=JdT;p~dS@LbgAM|Ec?Kc1JuEqV_K>lzS^~6LL&$x# z(6-t-LTWdY6DVfEkU<{g`$r?=NN_;FO1W?qLdvjtE1(*9n|AXSoOW_Ka2HDe-QUf= z0~zt>FcjVFISk2p>^lq%PyY=}Pn%pr&cZ>XvLG&+8YbxN7D=MMB(;#F-kouayF{9e z=fT*^V(PFM(@uA@B(>xdI|%vY4$AoOq`&}e+X4f3qH!H&am?a*WUPxPfEVkrzGBf; z+H^UHK;%RXta?bZ0n^y7Q-t9txJ6EmN7x9!=Mgg2wTY02kUZ`~;sJrDh7nFpBOx_F zoo5hIgA(HwLK^;S3nAMGX;b{=p#X}h z*Ae_|Y9a(yH!KAF%&_MM`#nQ{Uq1`I$ikmZ^vSC>)6XY&!9(aN%I`pGP(joEHKe%# zuX-P!9=w8(W*C>w_0N=UxhVPko$&h{_;WV=fyUWZ-YS4{6GjM@Zzt<9e0Gwtu6mr6 z&Ey1(6W2{p6+{hf>`4&!Gq`kMhV^3cb1-S``t((n2AXmgOfexqJmfK!2B_*o ztW2PaXV`bxzV2da010U?(>1EF^B7{7jeZQCx@&Wc;BZNG_`q&H<3l9h( zErgKmEDhk%h3q@v&g)?y2_csNKC$PQ5< zAcWk(`o5PCl49ROgpk85ZyO=x`|No;A>@^WfQ``H-o zBZQ1X!3gz)T+YV77v_bf*-r>LpXKd?GFiR-gpjwg=V3qtw)tI22pMAK0DJTVE9U?q z$5mJsqe_8s{D7WRFB5OR{0Ge`*eI(t4u2swv+2Ppp?EAt>B z#AV-y2_YzF5<+0F`4~$dgVo5sgAVcu_Wcm73zm135b_Sz7tlw3h@}}PguD|L4IyMg z8HY*GPck~Zo)8jYaQW-YYe{}HoHU$xh`_3P2)FP@2vFjE1Zeh=b>v*SpESeLZ{B>9 z(51&FZ)s<*w!$G&NG}#cdIoGnAmy1#N`C5c%h_sKO*h$A$u*!L-*X+0c4L#b>{Qcl zV$UZn+r0(wc`JD?d!K+qmT-H!%o*)q~AVtU1WTCA{iMPi;X9vW0BaXnz@T*UWb_>!&#mTlaYA*$i&ppO7cv{ zqf_INv8bA-kJWP~8?v&I*mQ7eVmuKYA4*P7d0KcW%h^!09Cy|>K*!j;esXwZBA!rd z*vHd>acD|+aI`i~PQ(+#Q_*;GXaEv#W5c?a7j}T<+L+ElV3EAh+0_jdoFOu*BT$xo zKg-@o3A1Elt(!$=7>dAp`FNZiNJ72Pgr>>qfzjBYe>_4JTHF+m4o*cA$wSej>acY1 zVTl!H%!27ILeX0XCWekCSVKho4d^)FZM9GGslH)KABg zb|xO3IvkzieG-|s;}OOgggjD9fWiDcuqmGf+k|#-;&0Cz8B_lZa34_Tb}`yHYnHwn zR5R_wBb}U?YUk5@EY}WXAxb#QQvy$QA=ZBZW78%tMyZ4za;yi%H|Y2;W^X6x+lCKr zq=x}C!Ge+6M#v*|WD=86S*#Y?4TI1zn@z*9Y`bIVg}i0wjK$8LcC{%XK59ALH5^x+ z$f=+bJC`q!PpeX-81{#JW!|3Bovap0gPBy(4T04lbs_|-75;<;-Pb~k8Xvf0xlm_s z2!EMQs2ft#Gw6^}aP7sSWft5vCo9rxEln^UXNiMqF$LkyUZg5sax)<{AWpy*1gBfT zngBNpGA<#ksTanGD{~8I=2G=*Gb=R21yH$&}l_{lNbKZ0p zn_4r*j1D(Vq-`T(6kJo!Ijv!>6)`c4e_NX}hLg6#T5ANipptEjg58><>6&Zn^F~ff zf$0z!w-&ROYiYMzC7W7nr8K=*%$aG7ZPeNX7Dr)Co%JTG=$cj`tTh$&StG2q!V-cr zeKk>=UM#jYIfgxNrVS^oHE9|r7Wl5I#?S1DrnLs`FVMAM*x~z>cb}_vLu+O3p14DW z(LS9$Y4z+WxCx2zRW~eNf;T-!;8qy5yjch=ly5rzMC!JpbX=?o*ok?ybW;fnGUXKs zI3F5l4MU(G++WJxD(!4lwi8~uEC$+&?F43~WXqBS;43Zl&PA^%O~O4SF00SXQ&L(U zAUG9K$f4zfXh&%b{)MzwV0XfO9bvs_(iFCV)}djowN%I%juUcRt5`HL^zFQrE9DuL zvJzBUrkEX8upP3AIaz|9eH&M6SmXN|n-01&Rif}7+B{8bE!&TjA?G8~$0(!vu@qfc zZZLb0@WKm5YWd;hSjff&%yjiaCam4Xy1aIvjTI`63leA6WQp*32;4T7A4hFjvJ@j- ziGgT^!&DHwn>VRD2yA9MD}nX}z{V(B39u0&ymhN8Y^C(nVyXmv zTLWRMmb5TVwH|Jcfm-V)hhr#sG}4x2GK&Feru}IoFIhuCpDB3B4a~quaDnTo!4a^1 zHH0&EQO4L^dvO3`S3?f^SSDobcIO<**yYSZ={W4shTSe2t#DqlCsi>vwN)`T=hm(U zW787RQZU5m4wKSTrr|VeBSx<1XlWgc3&DyWc%Af|=Hv{cxL2Do3^*Ql_G%eZFB-N+ zcOhpljaysF=ND<<2G@cMj_iV_ry!0kGD)_PG1D&8wAf1Byc{&+hXi|cN6VMe*~_%q z62zW>>+f0^<0OW)BG)u)y4g|+1YkJ_@>>}X1w@|7EH1I@03C+4R-jA1e*oEe9&v1{ zh7xEY0efsmPq?q6qsna|5Y8w?!_Eq}qf5Zmr5vu79<7St_2B<-ashCZt8L%)^!r!5FHNL}spBSl^z8;80N2mK%nKlY^1Lk!W&cf+}@Ha&}zQTo3k>ka&G!Y;q`u zDi4uJ;_*5JS%Js2I|7aCfw8U%ut6y%N?}bE#jL}YU#KR*=7|J#ZoUXw5mCaK%!HV( znRYv!vkJ1j_4K!QlX%;us2jjfILGiv|21SdXp^{9vMsZ^ZMfN4!?I@$tP5#^qIq%fOsut3mR>AuGdjx&)Sh@{ral=pUBO0bEiX)z!CjbsPv- zMM`S#+BiU0jq;u@hXb%Y=u^H;R7VRmPuWJ%-`C$4#y?fb4}lv6EVi(}^S<4K$rmB5 z71va_tb1<07?yoQL6NSOaL|&HyU_+le*hVK0yd(+$%d_{Q4pr!q7SViVS0e{&id2X zGujwrZxKfqX+4ucL17KH3<775kKnoYBlYBR73`YOhXETS5U~k=BBg_ofB?q&cE_Ig zr*cf!xI|6mgK<_E(AQ;ZvNG;_ldRQ59=sOMg5Yp^QW%#DVC7obM{6kZ!lyu9ID&no zhQN6d*k*uoP$*r`kV_3K40pjSufy+E!E1e0@cLkl!h{zL7g$!aFe}uCgE0MC7u6UR ztp&rLDdqNR2Ao|LZPPJA=mfe~vx-K6M>?a_4$=e#S-s?15F$OTjU*D2ac#jiUDqgR zW^IM}zZJG^fn(}4wO zg|I}Vys#up5Ab9%i%4@}AjYyc!7zrId|)Od_a-?zfIsJO{J~suU;u8w1OW^lPBf?2 zVE!asK6EodjpfwUlA;& zgELDR5?mT2o6)f`LJLMpVZb&jkE;TSbyb1Hk5!OR6-X5sF-33G+0`w%F&%@$z{+PH zhg590tp&Jx03ji+=5JHUld56C1Om7sQ;HV!65~YM4^6M4U2RVJF9&s>cn`Xp5H^1UBiv3aJggs_oJM<#x^&hC76S&gzO$=u4BrmL;)kH`@b-NEwx_cTEi3BA zqGSA}WVdRFhwEu-hg(;WI0d3LiboXFIBWBQ^U4mK*?Dpe0XvN{Ks#HqHt65unse>x ztj!x$6>zNw;QFuS&Q2dyflKb6%fQxEM!x7SYDL{~7A!k+wS=!h2vVz!SPsP6rlBOX zkPP5)*tFe}p3}zkbk-~gEJ|l>zIoHb5O!|M<-Oys0Y|Q3jCFy_lAg8Z^g>1C;sb~3 zLdTkM7j)b3p;S6+^D1P3DfUFufP_F5$bkTe27Y(-jqyig(Xp`B3WP(SaIgxVKbodY z>g(O#?`5z8ph-|xSkj%uAwGC!0Xd%wISK`i0U*xV6mk6XD3GUZW%I}h^G)b}eu_q6 z0g{zjDEvMos~Q55#AmED z7PbUwqqU7TWzw7HEPk zQNG%i9IgtBuCJqipGT@$@wqqW7M3FpxlA{E1{O9Vw5bAv5Yb()bTYD9gAOZ{63wHh zvql3%5CHs{H4;H;xCck`=A#qSQ^~=D$;8B==r~lrDKR}h9v!6*pt~Ds({j3PC}wB` zETsecLM7-z%B}{aGJzKQ(=8b*qkE%kU#;Q>0t?FS@2Cmt#iV)JaqQG!f z!Ah1KVBhn`)nPvMiohUS4=U8dae5OHyF43s3LV3uGL$mxy&ARhH&Z#ogIA~{G3>V1 zCNm8-m%`Z6))(5SJPr*3C4^CMQ7i~hX}Ctdh&EpBdEIdhTTKJFZ|33P6&4PXX((sS zT5ZL`Eaz%km6w&(Dv&5hOY6zau(KQyJ*g^UB41fyA*V5g2D5tbn>>i$t;*s+C5`N^ z7fAzEGBPovMw+Kg>gfXwGX4?DADEu7*4hzfO$m^LIMYQxY0;>U#uY}-z3AeTFuqZt zQ&{|x>Eg41B2h4<3Xy1P^(oblc~5URjf1HG*32qoN+$Gp4e)&v;qu#tjyC)cD&9Ic zF+MaMOC%#hLsQW>^?;%667~%B5Wo@=Un~-jj!qm&4vs_z4fu$M=gl=09gf8l<@va)3fhEi;d!K)1uvg_jcl;3 z^qiAPL9ax^;8c1b5|1X~oH{yAJ#W}pL|Mb6gF_yrtq^ZN^Pi zZN}%B*XhF)hRz8IcDPZGaK*CX8CJDxeRz*Ju9ugdSFtr4PC6lQL zP$3~*_I!6%DiX_*E%4T`#&CdbyrM}WB`jd*sW40Sl23bC*DEY!D5FyvF^Y=(%NEk{ z^<7prtX4<>%ed^NvM3>qe*u@J_pL<8<6XBj2Up>&XgSfWK^#S27#fcpg*X;2*Sc)y z`cX-*UeWI0>MR=-Bwu?vCo6$_`@FGMhby&s^noWReB;~%b_z*cT2b7|8qyZD$UUB5 zyFsTuY87T9g-qN?+lEUoESq+WOu~wrvxP*~xGp|1e#A&6tU05wud90>AbHbuM-oZu z0Ry8aN|oqcgMy@xw;CZ1Cdynw3A>p$1s{8*u8(b`SRd%!S3~-Puzsh|FYYsQIkNy{ zgI)Esuqs^NSQV~6t*UyeI!zYVQ>tKvjl6*xrZ`4!CX}VeGFBmH7T85KtSg4CKs@%X zBE~BxoBr`A2YoDRDb!cV$cML*5&%3_Oif;VsWgQZprpH_qi+R{Jb{LIoJx=i!-7mD zFqNGi@8Y<$#25om1sKb<53X#wJ*4~9)z&K&7mH}kyasYdE!yM)HbFRW5Z6=i|Gb&k zb2%#=qNfjSj@33kF&RaO868SaPDMv2BGd;Zjm@>)MQ)8vPms4w9!-o)j8BgbOdmWL zouViw6RUvaGh6ohGzaN^;#(;S!DoQ(=b9iCx=?PBqQ&icTH!Ed^<*ETVu41jxvNX-Vj^vSgIrA4l z*_9BwzpFcpe}wv|6+BgwcwKC=XxOHeftGgmIJAfWZ4y%&;fKWKtv)IT&}a^TX7BU> zFrOJjWI}^<+p|q%0O}G1?rK<7ZBoWc=dHCmE!aT75*bEr1FaV)!5{RaHk0BSo$c|& z)WrC3a%ez!Ys0h!NBgMFq*?=tFOTj~n@K_Z31~<2RCIDQG8j!Bi6usoqfnQ0)J~2> zr|8}inVeMESKfH8y0{3a$Qy2kd4XeW8fftbD1k>xVSO*MHjHvN)?>MFJJ{d>T!qVf zer;#he$>HrhI{sPckz_hz`aO${Q$lH87kW(1W{j&T#qa$Bs!vs%HYOU;(-gqLmKkVz%M>KF8gBHI~)Z)#_*1%l1zqqC&VI<_B+^~wRC zTuKh8BhddcozDew2j+bUclL(#T+uAx0efvGb!|{a<=B`_8vj&wZ{8iy!GKbJn6>h9?5K3(yTRVW2N4q(ti+V)D`82%+r`xL;xU_wMU=J6$zUS+c74$i=^ zcEP%-AWQb1+QJ3ygM-*(tE=rYa=PQL)k&7>V^xDYf!K{MRE)i7o6?S<+v%)#Cqsu< z*l%h@@PTiiMI}D?^hkW*mj!_{pV>tdz^6#i07hvVUPJ+fjRtKEiuWlqQ};G4+}GB* zzYT*gZT7VJ>Y&mtmKzN(ZO%;T1zjm-J$+KucC)3b?dBV*!i$b*ML8}&)unh=LBs;b zwarus43KG2xcTS>J-6tZX-6}_hSN~C9j9m*nZ25m*1>cUOcoV~Y06e{5sZ@PzKBqpt=(*ew*(7?;VssKi}J=>EDu;pDCA6i`tNh1fk66p0BsKaUq zKN2;(fM^BkK(_NHSM*L?X1G*eN14R~f*Q77F zUWfH=2~a?VS({l73ix6vCeA-^!2GCUBVE+xEYA`{Ujaz^I{NpA@s9wKie}M*)mY+u zjg3m1iK|;WU0%0(6M$R?tLK?jUbx4>J#EbvE)UVs#N{m-)}vv3Vknx7jvt1eHqka^ zY<)pW+BFzQL@+65v|B~Dy$Flo23-%9l&5>yXyUr}hBvhQ+L)%NMgOQu(^96a!(0s#wb? z{szbwlq>L)lU({`QU*r71$~ihE*CW9>hC}0`SC4*yH;1q0JZPzTAf>|QbsKSrH@#^ z7os%?+}1%`shlygmxkzn!~#p|j7;f$&P;Yk$`%8#h32mn&2qZ)FouantVu zPpCkk&~pp=A`O=s01xc=1g_bvM6I+=ltvicQI(cAJ$ogACFlqSBa8#Kh`utuqLTac z`0CE2mwtb_+Sp?oGu9gM8g)ctCkjePM&>=SVFp`rJRk)N+Q?H}#mYFBYnB!k7TP=> zr_h~^2V+ywgA+F-2S;Ntf;_j%zIeh!l!cS=_*8>sqA70@=Kz#}KOI@x^EG4H^*7oD>#-bDba`dl1@oaOUI6AE26@L&xMIuyxg4Xp;@ zsB8BARmMDsl6U(WVP35`QLcyChFTlZ_)OTS)8<$JMsVO;*VP3`)7%h`kCY`+(F@|s z3J%N{GfN0uQWFe_1=i*sAAJww>Bm3% zW(k3g8Z&Y$YM?TT6`Iz{X$Vv|U0q%DImfPLCXpsCQ~Dxiap2+=g|PUrs3HJfl)zd7 zTKpbT5?kbORM5{_Ydnz@k7%?0Wp(vEGnV6+xi!KgRsJgrXPqxOMky~uw)OP4S7O`R zN^zuu#1La|_Q^}?)CaAAeD(~iT)uBTtC!iqDi!iohIE4Z3tnaergE{O0|>8z2S z({k3VgEAHi2_u{tm7p^`>O|I@&4#E?3)9-Fhe7edF>Ozr1%lBAG1gPbrp5?k!ldys z%~^C@BhMAPbU>EC3!s^hlglB?c>{IRma|Vri&Q7Z|7iQf}X$ z%IR}PDyOICoUEbSdl3)Z^o7*~aHXH|u9FH;4(c{5{JLUz*&p17amho{)Vvu=ZI z2I2g2A=k_saOP~KZa31dmN8r-4FQ|e)fpI zTZ%mjB>PsMdpc)|s+-UXfY}4F_VJH6$3hiUU;qBjF#hogd-QEj&%QAJ0jgD4s=l6{ z9(d8y?xu@jO0a>iOBwHLkIV;A!Wg3#Y^mJcQQ1=2CloS!H4ryx!0)hk%}exOhm!?N z%~@PeIHb_7?%9EaW zBQ)%@HlXB-rD_Okq`%&K6KsN&T6!2Wp>f46ZrG$Q(BSv6V7ggUv6V$F!(LQGNHGpR zbj0VujG)L8JaiQhuDhdSzt2JuF|4br3&p>#u;Va=|I&)A07jBZh#mq|0EZ)y;ihSe zCD!=GND*j5^s#~vd3p8oAW7-s)%9ANHQk(!5gXRTOy@9DGhHz?Ju$Ly%$%I+%wE4Z zu#mg%X!Nj==)SRk(w?0fUl{1<@7>>h?8wmMYz#%y;aFlcGLW2_m`Hed$Mv)Wl69;j z;N&16Wh0-loSqVR!jQrf*>o$NdTSP@O-)=6vRFV;I3M;W1sbCADvyFVutXHZK&$y? zX+%UzXCI-oq3G#Zx2wXHbE?9X4waj$23G*(!Yi0Y>2)>>kYknXw4s3#NRy|$8u;pR z8I*Q^DbUI3cr8*n>g0583}3FXXT?@h*tZ5z8Yr+<)Kw^*^K{EjXa%tA>*(kTHe^uF zCq2AYS5GgC$QpoeJ_O6@s`?CQoLSwA6`-J>#70T=l>tzgIntr#rVt$~r5GV?U%U*( z06MZ2;jA(|TKa;%R>4?n(WMr8UE71VHa857$AuDpJ#7nj;i`vFo&b%TjzkCIu|(9L zP(os@9}+RPDr$oKkmxy+3m#e4s`D;dhbQ1;BdB! zMTf;t$#w}FEN~qwv#-2JuB4)s&l^TN9TE>N;)GR&i#w~r#iJ@NE`NN<9B!E!PlSG# z3O(+!t0?kD72W^Pc--T13w9TR8$*qto`I`*(-8F-PXZvvjG1!{+m!Lx=rAmWo%~8U z&q(@_6bF+ra3Ywcl)^%xjP7L7)J%c}#LB3Mt|6_J)AWHJag}UHYgLK(0FX8A0xqshq7SZv(Gac-au)Zt!tZ^pCBGlGL03>D8LLAl0zkI^mZUh%3V*eIH=r%HAxc?<*$) z#j6sDj3H4#N^z4mzZSe4|0+*j1r&rE!F@7w0Cy-kJXF8X0Zk`L(ihuI zOE#6aIo#RS+0oVw3k1eJ&|t>HI6LmFZ8+i1?zVl3FTH4MRj_|vRj}W>8t(LiRxYQf zEI6^AH?+KN&q2%?&B(we!o$+=)1P-@ zNo7V0!up#x2xzo|IyrpmO9jwF;OKd)%g@7EYv}iJxKw6e6s+>_g7c%yBLqGJ^b#XM z;M^Q!h6~-+9mjNBy?_d;Ep#CGqpEQBe8AadZ?pP|%3in9YS_)1fP$5{>;RYY5i4(q zTRGuk8*zcuvmIRCGhF52<-KFq$_3_CyEe;Pez_}(zX1%5I5I3t02M&Aud}N=jDN(5 zeE@)PodW%oXtC8d)xfj~w}i4DRX~lMmF65U!AG-;n^rZpmYL6+X>^QV1J3(Q;c2>F z*1K(JKt?6zk+<1<9v87u1c8F_-8eLm9GQqGe2L*sV&Li<_|Cx7@;wJelNAg`KPUk} zlqyKK0m65&nBgo<#qwZ(^3}~15o!ebv&JHWBeC&lax@y58jp<+W22Qu2r;C)qXTu# zs9GRFp6s5t(StlT@EOfN4vkSwjUtA$iG7%e#PE4!K12r*@5%^8O z7}aw>99DKf0_MuY5^(XrJAGSdES-QEx()o(yj?#7UI0kv!Iy8`sCnlyM!_j2o=p@FbZ{p~KPxK(}<7!y~z-b87%bX0to%=#G9zr^6*_n>E?zWClah5)E zI@-G0I(&o>396z+a=!C=Zq8U_AK|_bTyDHz+0=HGzO0I~xu7Zuvb0VK^^bm+E8%8h zI3U#50*s`&6(KlGc${02ZcvqoW@B1PPtTQ#nq%ckV35cKNjeD?#YpA>bM$gq=rJR+frwC)lCoQt=H06L*Oa|Ln#e)%6ZG33_RONX5dd zEj@zX{eZK78qdtT1e=0rtOEBzqS zGA#r#V~gBJFM#EwG|9j>;A&|0o&s)|ee#}%H2z*7Y*>DUR6+;RxsQ)!xuJ%dXvx)~ z?t-mhEgm1@q^)dtWvfQKTViR5G)yhvSvuwObSn5uyHhm#13NsWK<$ zv~zPq+M-OVJ0PTZc#{0pnv@?WDWGvuk$iuQe+-k|~5`N0zs9Ss}I3i59*G5@&^Y0u@KJ^_P|1(h%Y zg$RXqyoXcOFv*;CSbiQV09Aiy=l(GM5qi!Q9~Swvpp3-}X|0^l!jcLlQf))2QJFN@ z^;-fAtb8L3*d=31w5@D{)z$fdRR$p=ms?!Bi^us5jp)apc>ZsqL!(L6lWiKrQt)2#evTNa0xUjy&#aN zagLaG7gr)Oh=#nyMXzal%3S@7ps0k!wU{Lr01`e z!oMXb6{K$f1P^&rd|49s7>!hbyuOZp;LZA%=FM={JoooXT=M~*I3$)rnK&KhZCT=U zxOrKsLEed%^uXy{qr!FX(!p@f%^mrY< z<>xIM(^-fRkvBTK@Kl7R1r32rTVlHXcz%(_`NtCQ7H9m%Z40DH7EN(YI;-1`;T|Zt zGky8gzDw!VN{0>GF|ERZK2Xj=`^v5-p-tpR3iKBw+%k4Fe*LI8z`_<{n?T3})^W3^ zJxUg?@{n1$LD(j6(%?OS96M+wWsX<0Cf=wRS=){A;NOa1xqi9g2V#i0<3`2k8gTc0&TEOfhBC|LAztC*CVB-I?D?ApBZDK+?Fx~ZcXH2K4yXmZ9 z@1>m1UZ;>Ry0%`->~$8MoHbjROt16;mS2?#;RVfg88wPBnoFp`F+CCJEPeu}hBhjfO zhG~x>VKm8P{8B$@nKR6EiB(m6Bdd4|r)G+HKtbn>#s;RM<74q;e0*#&IXE#kHa#9o z9Ibk2##q_XJ7I??@<=q27>Q1eMJB5*?q)tlm$&z5m(%~CofiZYnv4&QM2DtFkqNJA zAg<%3+eY4UjijE*P~LfTVmKL_OdgIP?_5<`!>lYZCtJoMHzZ@@lhX+(2W6M43gXML zzN@Eq3|IA7bZlbkXmT_*7OS2{!AcgWtFE)F4@%iKF-g&3EIO8q$8M~Cl**}%Yp$#6 z&mq>3CT5h-P7UrhO+_Q4Fvtg|CdR6!2kwWn^@h+v%U;m!jFEwF(8Ddf#F1!ZXa)Gk zN6L$T%%*Hb5SV6N)y4m6{=v+(>Uw1ei9XQ-^IC^YyoHZA2v0O2J z@oPaVS-({^DZI~e@7NNL#^bSx@s;i#T+cvF61T@=L(##=R8nFX%&mf5e4W&FQtIA1 zJqh<=CtoRbty&P@;NQaV!cW^8~;6*L{USgq^n z+b^r;_K7qNXB=2xXi@P*WGayurOFfR4?nD8$r`XmPYSMzVJWur6v@Gn=-{Ej=oI3R zuVFJ52K%C8!goTNhL0d6k~27wz#fyBicI4E)+jg=UOT%DU8Fu5ADtK;ABKr(;LMBE zXw)ws4jBwqg$g1lUh?TD@G311GNr|}K}w4a0LkS9HN^aLfW*I^U~gsbE43 zm}Hu22Nn58w@p2h3U{J~Vr?cBcyZtPG6QEQ#24S)KOhq20-9p|sXY?POTv zv=A6k8ikBi$SrD%hNFc-wsEXv+IZo*w%fO$TVYL{D_cSf6E>2#nCaz~z9yip@p4^Q zPX{ybZeFF*w5{K(T z4{&b*ub7PKq^)@jmZ43KOtz0L#;+d@fqzzphxbs-PJCf;IgM4+EAa#YswHthuT)(8 zzL(rmnvo?0)7CI73a?g!UxeElmV;DDjncZDcuL!)X-osdG$wp(D=AC_U_f>$uq>g? zYgJ`dP};z?-@MsO2BkKo>|$}zFeX|C^i~lIA#2rLm7*YI>tz}|YP=gX0Pv}ztB=1Awg#4>0VJ1_1JBj!<@F(vPa;rK0-Fs?7p>V(MrCHj zt;=!mzM?A_9;@86pRPGeBdG`5CJOfP#Q2gAX}Ow`FG}%+mJ?vlO4Yzz@k{qZpC-3u z^|s^|q}xEHuYdOrS3BzEz4z_((0969|33>le}EFE!k`QK|8FQ+6{rZXYV82ai4Nro z$7SIJdETWKoe-^C!hN)cxv_A;r zVo|ONpe+wp?C|RkOD^#Td4mfRd>8tER^H$$)U{u6>ViZmL=(1@K1UW|P|3v_ZUO-p zzi5u(mWpt$h2{?Zr>spvB{HvJ`|8?6;(-n9A$qp{9t;8t_&{xX*Y@aIk(3MFlO52B?LQ0fZ}?>>I}b=?*f!x-;fm9v7}QB4l(MkN4I95xmZ>&FY!g zdU{unFt?>5l=66-K<~^5%uGqt4 z6q`fsWAi1)Ok-q21Fy%T*RC5j8pKXJM!|5=0(QW36U@;J%nIQS_Gde27ag@S9}xO@ z3DkjMZ_`T|(|?^7&B^d)X=H#hD!@TsFSy0RAK`5l00_+W0zbF_umny7cwNxe(vDQ{ zb&amdOe!S$`o>kYf5hISIl&r$!+OHa&Mp=fsXU^>u^g&~+l#Znp#k@>esUNNm7wpn znG`>l-!x`qOr2g_iJ;~WYE+v^-N4K$Izu6&khU^rVfH}lbmCxNE1Y4c*MSu27=CDmq9-1?v_M|qeeCG|!nemu0P zX>elvU~D)!6ho61b|ftMsCx845atEThcMdA$2|nYy{zeh?@ApR++LtL^T+eJ1#hBL zitAW92Ct{Ty~YZIOBpNFV$kF=Og~GWxbxnGJNGksNd)ZzJv^jJUO%3(?1EXCHEfCi zdAthM`$J(2*@#!QLF}$-gSfI@InEAnEv^)`k=kM#$Mt+MXMinG7@tVj3Uz_N4wAPr zhAl%mLZ}1US?Z;nIE=eT-kLWJWaxBzu}zD)kW~$jkTNtKZtBVDX(JEb%;1j^w+gy# z@71PsfaAT|#JpiUhGFm3rVB-McDAwf>%dnIUSP=%^^|tB#NnX#0x(x8~jYvkG8G^_)YPI}8HVCF#!&=LVL607lX-b`( zXpQ7?*P@fC|@jXgh1vIsOBx zWHgQ{u-$A@A*K6tq&IHRDjjF@M&4R0b&e{$)e!JI5gY~enFPNqY>?RY*Wpj^US2qp zhCzhS0QoG?9_?ZY6$Qg`pj29ua)mLitEw&dlB%}gcc^-qsxE2I7VH@mT z^k59pd+qjm!VAt7tc4uhGQl=p+&*E$Dp)R9QsPxk#hmWK6~}VZg$=f7oAY{lF_g9n zPTI6e4wdaNw`I@j1$NU3NP9G>2u?`FeXZmem>?i15k9Y|>Y>E~UUBSPX2vR@WKUOj zM;QMsEt};n7KupEoCLixw>6=*RlA20nV2vRWzF~fPnj@44ocErTxG~G3np4auYpKc zOL*kije{eR@!{xLlzGnY7>kX^Cdxh9)?xFwp?U-OO@fmaNI6@TEWldO5rW=GNrwje z5V#a%NDXKtF96=d0uI5aL?gXug3tr^vtP~Td0tsT{jBIFi@zunJndTfh)ZTSXYkn}zZi>zIWBkhGDdyxwxd zP0=QZ^KMm$O5tl;J-tUp%#)O{wtTQW$QLlJ70|99tXS}mUS!s`$kX-1)t*2n5(QW6 zT#YAL)SgZ#vp2A50_xksxj;JD0EcJt?x=Gwkn!5noqI{!Cr$^^AXo!5YU{k=VmRYa z-g1tW)+&66$_3SWxuC7>v?Z=<;lK+v2(QKTC`q;`NpqIelhoxbym6wIfF}&#&rKUB zy9A#Cpz8C-To>GPAO#>3#Fh3SRMP@K{&AMLsa%QNY@~B$(J|Oyx~`?DHyTC1szRmK zs!-`ZZ;&I$(P!b(HyYN4avH6o-XuKcv0&jgL!;n^wY%8L%$bgB6bxJI?Ca}h&-7f* zT1e^ztFV{{#z@>dsZpy^P3D4?#&Q*H%eB&04z7lyr)S(YB(OYjMi-@{r;Q;gx~`>- zU7tv3dF+;M3n)MrwBNB6Ym5T!pRk9%>X}GUo>`$a=2_9MFLm1XAKub zU{NXy>MI|#;m~82a^9{I)l>jHn4d8I0Rraj2x)+LodWULz|+^K2z;_X0E9|SIcqko zyvuh6$vw_(uf&talbp%1v6_CjBQ z{sk(5hE;{Jd#b|N@2Q-hy!59c^C!$$B*%Bevgc-U)`F5DE5$4f-U6Ans;JHz$P)ATNG%|RhrIkAEIvv?-6340 zBMFWIjSnaN6HOD9X$X6I_xFYI&r-54yf^LeCM0ccPI^E)cAR9eZnrG&~w({#8f;v zF%=t*jk8NtBcmASkDcHFlMbZd4Y;5NoM8!fvxLgnr~zeIDu`DM#Z@&M{*W^)PEW827d*3Q-S5%m81>^yVX) zgiFe>{#i1x)Pb(ncJ%=Au(Eg%0G5bTRHLWfO|(#YJ3v=qrh1eWqw)TVc>b(AeNXnRI)0p-065U8IP+3 zwq#Nk=zx{VVMTCDTZgA2lOxxUs+B9Aoif^daAbeCjztqwu|W?L$C}3HoKohQ)TfcT zj6@QVfk<4PNWNsf3vip7iwCJ-z{jS(x0~MATQF|dCh`Z}!;?c@(K}po zY{HsK>HB(*MaHs6ZtNZy=o+5UhYDkZ6S>|SjvH=vUu5{ki6iqJvAN;Jq263tA2^7M zEFK-4iY5T8ltsp;QFeF>l5l)_GCJi$f3a!WHw>kF77vY1W)>FoM3>%m*tszt@6Pux z9v)uk?Vo_^c8C&^k;zyxF>xr0H+ZwI!7bL%wQcm&H)G{>v%sUuY?XNtIfL4Z`JkdL zGO-UZ`9Y>kyIrPTYEkja4z?YM4vb7p90~#)DcEf|J-a8M%t}WIl*>R{1emBw$+k*n z1k*ytMcVD{hMVT3NA+Gp)?@}#o=CVAky_-UR*1eEVc>|&3-7Q9Y*!xBZeS0V&FG|U zv#4fd54=M0%bB%S;6-=!1PH85D6VX+B^b;X`SKlJ${id!sKI?(rxdM)i|D51_2C9` zr?Fb@KZVBhK_r}&hmKjQF$%LAc(uEx9>aoA<%c|F0avAWxU4F@Lw2KLy;emq7K9AH zr5e9qk6M0N86$^!hC&89Rf1D;_|5Fs3Wf`}@QC=nl;A6?9dIymdMfCso0}9Zp@BF} zgDuuNcCNHGrdqAbNrYTUD%%6QOlw$etxvOITEhM++_@U2TPu(IaOw;F_Yebu4sn2S z8}^%7wsD2E+&YA&KcCkNneftqFxY^c0@$oA=93S}CXSemVY zGJb1V10?`oa#cp}@vc)}?4GLE)6hV`N}{2Aq>%3Qd!%A1clxBwkixoHsWcg9n7GPR z)A$Q^m1b9uF9#L1A()Sq)=~cF14BzxrR=g&;U$x+%ib|T8am^zlgrIsKoMD z;DIB`?_^a|Rg%S)s#~FnDp#twt(3~CQ z2BZZcur;he6Y?bg@9RK-GVmIW*lj-0PTKJ)=F7N3+-8zOM`I#e;~$x0 zMe4wygBvPXbAwT-8rnG?y&*9;Ix#(z#H&*TQYf-3Z?4RBrazZYWyUq1O*iT3wBb0h zNxZY}T$wE~H62exhmu1RW04p&VqhvVZl3DZu*$*lX{fm-&zn40AuBX_%k5{V$)g(< zR2MWTyk4PMWy)omeu73yW?hm>v${1=nt80@Hly3q!oos(*3HWsm(XmEs+M?ghX<%? zDImB*-6?nh{*Tfq1v{pz`Wrw*tCUghh+>mhmFDL1sx&trU8iVnT4&6hpnY3DU31>ROPKef=R@AI4Q^{E;A;t05F6J3r-x_LX-~FnZPh@_?GBv( z2v7sDfx-rtvtB}N_6JQ+pdXAU8Yms*0B$o#6STa}L+)DMEz-|!`_nNEpNHX=X?!~% zu=#SgETf`QU>Ak1F1G`V0Z{WZjSHMS(D&u*M2rvv za+)qkIOz-bEgiLn8iT?0U3~MD0>M@vcmu;AOj<=70Q4#f1$X^E5gfQX$$j2Yx4Pnm zm1dVEu7P-=x(w71ALmnYY;^2}sTAjU3g^T9kY2OYp;}F_+vG(G_kbO4ryq)G|9bkQ zDh}d`syK)t)#em>1;O)$q5QZNf(soa3*csTS942t0jx(CMF!0*xR#~|?D0-fPs{Bc zyH$B_$JYTHI~xaTDj%>!14gUjGVSm1=@3rQWL>2Mxr`h55W@Q1&UH?*V_tjo;Z+)6 zD%j&Fq*i<7WegiTv*s($6Me+z8n_v3#*?;@Ny2!0&$Dk}E;#TRVB`(Aww0Y{H>*nz zdYnNc;gD^p0p&J8t+r8JG`YQ1Ex$f>`AKVFu>eP{1-1fhYu48Dc{oG`Ut(k4D7c}F zZO$77u;$LO*ctLjm9}+>#fE(ea9LqFmsoCrBUE9smPF;$WkYSRNA+s|c2l%IBj30CabB^eo32`>2n`i;>hwOU6S0 zL2*pO@6IgB-Pfm8-zuPh4u%&7o(E5V-*YKw`1`B8Z{LxcHBg9Hb6oKtL{odlS}5c! zJtOVc8u+9C)84xPNs^rBVKw`jnSI^uz3+fK)DHGAx8U@2&ue$Kfdw!-GrK#udEGqj z1;DN9s+^v>sjjN6s-D?794N??6p{r>q$HCTMFwD#;sYWmniOb&q-l^QNb@053_gO7 zkVVT@1Z~<8a)fBfLHgG5{rRY@N6+@|%`HfqeHYWcnSW;f`RAX1{`u#hf8Iy9$iMLn zzrls?lEuB;DpwXRk`st4PDHDoga|H<4gA@iJ9nNmjDb6M?%a9YFb0i>4C7%#d~^;xMf0%hmGv;$dHn7xSaZKhlAvp6~aOC5vIG>W)1Lz`T?v+}r_85G5P3kzzf<9n#)M4ucGVk*j&q_9>0qhz zxMvR>ERD;){!WyK;$8Y6Wd7cRQqPYX@)Tx3KAVm;`l*%G`Q=yUudThBvu2^&gB-(V zbQ`|0pqF;$lP@UGe9}V7iJsmwKDBUb7i7o4LE`^>{_st};RM=Pwc{ zr=Y0Xgrq3FPnzc&%?>GhCav^&&@v0E##JyRiU%Z$W`-j2`sj9%Sktx32qbrT;$Vqo zC0dX?MFdSa(Xe8=Juj7-1IY?`bv8TLN?48G`(S5h+oOMhg;<{fw|UUwA*kq$nAs6a z8as?OVQ0ZFGYjNrBkp&|8QXDnA%m+xO30ielVB5}DShXzroo@$JE3xa`#u9t!WU%B zkc@2z)~M{UX2;cj)^X=UAEJ)ilXR)|BwfBumoApuRkWy^%BfV@j9FCKid^P9-abOy zZ!VDWVsUXPHeWzgA{Kf3=8ET8ZHwn$lt+PL5_H^N|IDh=O$3y@p?q|Ha}6M8aDlQhyScVDzdXzDkMZhOgj5=dZ+ULQ>eXuX`5hMd z%o`1(;0vLwl69plwUSpBxQi+FU2{;tLzOt-WE-y{? zuUb)3nY%_*SXf@)m|32kPj8xKiOL7!G#rUV*vahh2xm^cVy+uO|E zp{P%mizrWC(BkeOQaAfZx5t|!LPFJ_ znfL$`L{|X%l-Eci7u+7ELzfkInxFg~sD=yqz|D_&F(Of{n8Ug_$N}r}Lo4Alb8uWz zq)T}r4C=*_MZKIuv8rF}dGe`kz$f0t$p_^?h@_uB+|5GhZU^3jvUnU(PhuUlJaTV- z`ufHq!jU%|KW^|qcCO!A3LJh0%dtaHWRN*yCV5VlM65a%?Xsw0g>FL%MNTp5T)MpF z+z(EX@tXswHAY-L#yWGN5MMcD0)g%A4y#aTu~<&Tt@K9>1i)XJXgFmuK+uX%xu z3gt$GccAM661o*|bzGQ2uQ>y%Ew)azo)v5yEYSl;`lq*)fA6YFr^*f(fUd&3C%H5Mx%8)ZJN5Z*vk_7c zI`t_rm8^Q~wp4dnY{J7j7!l8f(I{*ONgxi5Ll(t>Z+ZOn6Y(M1!cM!+!o;Npb0N+hlwbF@Ak10s9!i#LZY13{K}WZwycgP&x_dY zghjsP)zi4JJU+f>`P~IG=kUBx_Sk{8<&?J}dk%H(aB(Wdb2rxPBA6$}Cu_Aj|9jBc z7j04N*;}y1htP5o78R|#Fpn}0rdSIz0g$~%zS#WS|BZQ1sNI!ZsT z%+u*P*)un;^FWsi8?TidvGuniYs>Pj;sM(e#e(vPO%{>|Y$wuQ<}bq?^S7L)jM%2Z zr5C7Vr35L_IAcZ3@<{rGdvs7(eu<3=>B|R_w@HmW>cDXi#yic)J-`krR*Zw>=q`pb#m%BE-B@?WIC$ zVx?@jPTiD|z)f>2@EjJ^&EXUX4*}Nc7Lrh8O*04+H}K=SO3(_D3Mxm5ZaKwnfbCs1 zMYk#zrs0z(O;hVmV)3_P4(^W?x-YW`wWgTE#xKgISjmpd0Yi*caGHiT@0=v41ia-@ z01jTE2F-6x)?vuIy|1MQQEMSXM$_y>Ufl$9Xkb7Rj^TBav!a%T=SfSF`Gv5L$ALeG zvrVmlskSS1b0{Mu_-n50fBb z%6+3~r7QP+S|L4T`F@bl+jQ|zUCS`dAs7LM>gFdDFg|Hf{uyd^TrXMhhwA3oNCwh0 zhf)s6)h)_mq=)L}kQnQsdU>){Y{+@!R3Lt8FbxmU5OM#zk57o_D+DTA4+};QRFLA?M z77@*bX!*>eRE1ogDGnZXMSue*c#&?B%2FOkp3jjlMHQc+Eth%D zEWJ!n!h%CW=H*#mu%|8fAkXtuGiEDBJ=u;}yd8K>oW%s695z(W?!-yZErn#J{GzUD?id<(kDC4UkNRo;1?DR6t zp}nEHIX+oPzMT~={4=y)AaEXmyb!`?NT@a?{4<2faFe;MZ7}Un+%6D%Xe$U325DX# ztRXTOtp$6inm9h+4=F(aFjT19G%>y%o2u94q5KTRopy2dY2s9VhT`o2lq{QeITB$i zYzKQcndMNs+IuqmlY<`$y-v&Zg?5I1jE#?ujgIAdGsK@@K}YjFDIwfl7IsYl-J6uh zr$SmJ;>aGMJGA_l8#bIc5h?U5PONs=aQ&D?h)00XYUU@0E@1!DAY4A#h0(Sa zNE4bV!!;%}iUVbW0$!(0%3Xe3`KPQ9ktnnxtIZM?mGMOS=~kZVkc&1aObO=cN9hGJ z(!#22zc_>BColWtr(}llPoa_Wx=Z*9pKe_}R8ryoHF)PQi6zFYmX3|422PcSD#b^QWwzpZ^N>#W?eVd+Gh0WJc!rFMK8MM!i zQ;$X+x)|ZYpr~m#)Qtv~bgs3yKG&k$z;AF2M+qc0Kk2`6bAD}Jl;C;hRq0(cY|bpt z>9s8`yf|+TlLoYVrSbgmC;gSRx%oBo+G`qAj<~d2wY`qRW<021rRw{TXEhlqXd7fP zNl7aBOzJ18_Em&QcOSYTL{xA~Xoyk+{PRYmh;6| z>1I;Xn1*1h%(ES?1fwZG*sEOH&JcMh2}DlXP`GIojShLg8 z4tGt{u^4V&zX|)j7DG5Kvdog}Ua(hPSiQdRssQg&zd*KuwY_eR*QTaK!!iRy(eT+` z27|PzRoWWH{2mld_k0id<`L%gR(wmk?W7gJ0uJjr@S_L#0{?)@;#*z=Vc0T8cqGE8 zoiV>7vBdn2WO6HW>So5iF6k}5Mb8A;I*7~`NS{s#WVKomYgq}an~BvLu{|q}N8-qC zv@LtYi4*$X^(>zft(ej*4uW3Lzv%}GVF)ONek69d(o9 zFkcWj;FDM_^BNvQ+aU1e&BaAixZdjKYZER!aolhnbN1%U+6!ZsE*9a3&0$^6w=Emn zDSYGY^Ah-4UHw-m>BPx>lmyq9ckhf96J|Yi+=>a8o?!WI+jM=Fly!HM{>yZgn42-o1buHfW0V3J*`CyVn}x!dsGs)Oo78pRhPT z7CHb;_8uC_?lbr)AM8Wso||k3orF?MtZ`)nS*wjz=zp_TtJD9PLFJWqLdSxkiB1s9 z>(((}U0Yb1S$oZVasD;)1;|A;YkBJd;xYgnrlT?8D zw#ENFHDV6O$*{urg-avmaANb!=@E07iGo+CMxH))dBhyHLr-zi?Ov+b(SE2?U`n=Eu{y~%)q@k;VeSXW|4mf# zVqWhQC_u<4`cF|eP`e-axAodDsdj@fiK(_}N{WMu7|CgLZrAmh$fjX%TM=(<8dV2z zxTTTf3TlYM$W2%!3T>+O3Tm-#SH`FKKRI(Fyo=Aomn?RA+mM{}Qbju!=(_&@W z#QlNAh1m_0ri(eZ0;zR#VfjXG9^Y7-S>7iJa@?vI-%8K+T#u!ixOXa(O9}w!9GO%3vq?S z@R=s}oPp~nccjqVX}E8Xg5*a*a8QTqx&Y7n4JqFqx)!ec2#Ioe{n*w`OF&z*kpU2^3F*Zd0J zw(l+V>!)r<6h>u0{-dX>CsRH7-u~u0yLuw9B zQA^`dQ?(vQ78cPfm#$o@)1QN`uE?8!-2<~dCU3Dx)MPyLVo(#)>QkKM#-=65@GtrL@c0_* zg%W4~%R9L%S-f=tVme(8C7Zxe-$$%`L-fA%n+|NF4nBqFg3s3Ns1>b6AIcBwQg))Hr z^i>XlZv}ztj7x-{u!`*Ljutbt-Shg!it*Z_G z6AF?qc98iaY1*ws`_~?8HjwhE(e4}L7Q*w^>2JC*UJ02mc9mwk<0Wo|cG`A;>zi?G zwdg)(6znjuOP*PJX_c0!rI$7~~Lx$a9%>51SBKM3J(~u0g`(Ck%%# zQ`(0QoJMr-8{6uGE0#;rUAVE!sx)=!@_3#8VB*QHRm|ZrO5}glf<@7X$EK$z5X^j{ z4qniTOe2l{AVa@7k7}l?QwFp@!GHE7LofFvL%*)a&p0?b zamhV(u1j;3svYdQIMnuFB;cuG1eSR!R&9y7FL_ zqxz&4@9EmypMwtY5NRuNcd;4YiUL2W;N=3mBeKRE$4$(=$W0RFBbM4)Cr;H38iuYD zMhij9AuB=D5Hh3i{M?v6T(MuxfpLHiRKPtydj~ov*_W64%OCA zZgvk!P@Sdsgh8P}-fpK!w9W@JIi+%)ri}WVEl~_>qL)FKDYP&SHjE&-MS2#|mcd`Lr9WCmr>6^jmPc+yynAhad1k4E zYO>e;%(LWj`AD|)^%obGi_IZ zN3UF&IG}L(5G-YpiQ7p5nH)*imo`=#>+@?b&r`hQ?3hRX(sNRqP+YWdke!QrG9j zjv9FCzHm;bz4+(3&B%)O)%k4Q@&-RCBr}os{qqK~d@EOheCzf*>(7jG*Vz*&P2n8g7R&OKA+I=>>czWL7gs zkVkd2-@wDWv3a2rx%8)MR;fx<_R$Mg)QV-5_{cj+Wz~PP`AHPIP-tb#iW9rVW4)Sc z$cQPkUrr*j-YtAw zeo-h}Z||M|p!vzs7v2b4Z@m$+)>|!i>#fjly=BMoTW`c~xpwf@?Y8&UUa+-Af5tBs z$;57lZp319qUPjr=p zy(+bsZtAlXJW_}Y*>j(Yv8tups)2eH;xs?_L>qQk$b2Vmq|uttWd$l?Rh6AHRLtS* zGAA^xtE7o(I$SQGgr%1pu3hOT3op@(G^frQbZeh&F0{u)WGDWDGpV#=j(ML<`vxY{%&t?FB{Aq z^{7Vq8m){2cl9&XR#3I5WL--Mg1jO|9T|U)-@Ky&cbgoTM+8`;l$_oiXRe*_N((L= z6SXne-BQE#J11K`3Jx;SJuXdjinNfP*cLx~phSndZ44T3pC7wtiH`k1x*ME3T;I2t zSL>Uby0H4Gy7;*oM9HVB*ahg^SJuk7j zwg^I;;0hUZQ`GY`oyYP{w5l;naBrGiic!PkvWE5fjg5un8|#hLnT?xTHTo7ps`v&} z{G1)})UM_2uzhm7&P4S*t+%gs0%rw67489mCu-CtgTMX9Uy&7Hs@!Q=4#pb3m5`nn z|L7o#{}JPj+%{lDAS~3}N+q^-nK@B2$IJ>2pggwAJaf;A5J?iG5-)n-e1I1fU-fBi ze{eivjvHeaUD&y3<RMDWA*!;C;ktVxWF%=XiDjrqI%=dJCIf1hFHYVVZTv)m@SoY*+ zlumwn=5I*7eu3&Q9gH zJjbAxhJN8>s@8*tRlOny&!;Ky+!}Q@1x}X_`H0GQAMl7uX`JT^We&Bf1x==>eeX%E zf4C>HzO0LN&7)498n1)nR^g*YUbGJLI=7kWSqby)eY4H1xD#<_X*}9R9@)0#%M4su z4I)NfAdVY{p0zK_j>sR#NFuk{Ar}(<;sh=hn_dvdqiV4r&WEpGw*x6a2P|=SSTt&H zrxeUB7OJ9yWUgX!l9fqYd4~kDj~Ns`M@FMQEe0ACq@ zXWDv-I@he~;#-%!a!6#`jO{@(i+ZHRLa#^qRGZh6-C+Ec&d0siSG~O}b2o0y+^RWmPH)}* z_~kc)mlkfJo<})8Ybz@onaUm#NR0^G<+GN0UrzF}@+3<31KS65`#43Ap+@-gd)H=W zU))@6@Ef#zwWa|{TCozmZzreTe}|*+Lzy$*kR7rs|%5T>&5U& zdv|ku$-asnQk~-EVp*qL#g8+;vbheZlR$HEWp;);tmgrbZf?v1>@>jSn|^wStJwu?&%k#6{U}agLb87Bdc5Vm`!Q-F6XQ0}NqiT~s ze+n$-HkVe_o;MGz-e7%LLax8Ku-aH(r;WCRmTznfj*VZY=p*##egE7wb+#xWX9X5L z%}{hDGd)FDa0dWgIW{p-yF^0;z?HQO{pHiJ$NUa|0B;aLYxCC^Uey_*6l{HE_QmXI z%2AOhNJ?Yo%7a{)C(%37qQ^r97nWvj%r_PnuIcT{Bh8aml34aO&O1=&6LhAIhb$ZO zOV{S-8cXvVH&?iD61|@iy~iuyAIqKao~7c5Iop_-nJU<@U~5E%aO!(0g{XO9|^GXz*R#A;Z^YU6a|%bU&* zvZP`eEzVKpYxAp%uWhUp$T3z%j%<-UMWj?#bK)^-VPkQ<@$&rI!u8i0tMff|xQuC} zL_Rvj_YJ3(W?pTq&984RZqVD!l7{jre|A~GaK`Cg0}wJ`o{cHV{T#n zMV;H~qPM51RD(bDN&L3Dd2MlF_Mo!*RwVOy{8@DvLZV9TNcx>7?P@d64X4lH2sT#W z+B1-SYA-U=buV(nz@QgwOHZZ8*<#(TkByB^j$S4*h@?`hly)PCP~(3qZlY~qB=vjR zzFh5T`|>0G+BvnheUUH5RP>|1x>@GYj+fHq1syAn8A4g%>MMka+I?{SpzGd4{D-MpLTCbf7`G^2H) z{M|IRTzO2z99jtZhNJv!_vF^58=LWZORPa+GNdPmG+6*HXwj9rI;~2nTcQ&VXQK`Z zkW>jQ-Ru2ermJ3<}Hn3Rc&IFs!PzQ| z+?dh%xxH;7VmBgcE7dIUy5HzS=BO1~_BI<0qJk+HeUzRW;@D7#D;zBaUQ`JqW=G6Q zG{2gbI4#4a0M_lvZK@hpa@?hYnpT`eS8!t(e-63}n4W8)#&r5<$5~IRsgvz&)}Z=< z-l&SnLu38?;oe%pd&SW=V(z?KSACxq(+l4v)2sKZzML|k`w9NDr&;#Vo@UuE>$B{h zuln-vIsDv5JvmL6W6g-!LFBN=Of1(65b_3h3BRFNemU_9SAKbN_l+Cz3_kGW$Gas{SH0kz2^WtF+rN*kidiX*j*@r>p0UV3y zmwx*USjyCK@2RTKZg*lbzZ|s0{sZAD^zE4oj%ta;)t$l;t9$PRzJ+%#d218eYI~g8 z?@17RtS3S6sD8@pz#}OLVc+O#CxKJESw(~{npi-yLP+s@cNBeblrBOBk(2sR$FAS< zn6#z@TL{vbY?E-XJWmGG;*Yu0QE#&CMouNPqGaD}y1s>H>_;dTSKu>0iAN~PwADf? zj)rFz$PF8Q+uXV^EUC!ROT&Za?;G8pb$g(VC%-Q+I%d!DnE$w(otOQxVNXU9U-X+dK zoRekMie-ur`DSIyl#Nt*w^?FucS5)WqUBLL-UT5v6S3tdfgiV%3_J$qv|d3^0&u1$ z0r>41O(+c=Pj5|fZIp~MSEmJ#K}BKpQ}Ra10C*Ee~*lxUYl zQatJ1>8gZierPQ#apRD=8N%e`kX~ng`!alw!56Mts5fB8cOIAt6 zPtFwZf|NdYBTIIJvwGM=SYXFHhwRI@@7oDEBt8Ib=ZJBTzZ_wLXRyQpSDD|PgwYSO za7L@Nrh-qMIFib!Rwt{tj#gdY_iZJRcmNxSqhrbm`)ek*Uf?^ky}}W4pJ5FAyG;&& zZv}7`SXL4{(ztW5X z%dxFE5%KZv!KY7>P}B4VRbo%V?iz&MpWeB1=SjmDxO3;uoyQGh(0Ir&9yY{h&@jx; z>)IZva$0D<;jTJgNwg=NRk?l#5nE|Z2e#W09%iE0GC0*}MOK^K{?a_gp<}bjl0C+J zGuaEwATrx<1w_F84&F;uB2tn?#zN*gmIxaz1RT4~l}7D}Ca(W^mfuybs+vo#-Kjj; zfWPZTfe)ovr0`31n+tPSb#FbylfIEjlftufcPRUI7hBN8^kkj>C|eM6 z*kK*jrR>ecaRIR72*8xLb;z;W_~knNCCDQ_=qrxJqMA zs0r%ck0PGD_fujC{^YyKp;!UZ3HrN-s~{%K-u54q4`6n)dqEf519Y#(@lyp+b0s*c z1oE-Rxmd)vlDF9FKF#Ik;M5Vr7@SfP^Qhy;#jF#MyvX7qfUZ&5w@H%GHXx@aavCLW zrws(f6&sAo$uy@YxjEaDlKB7VN}|t_y&yth_InYS8#JoG*qmElH`hrSBomr%W)3Yn z$#xLAiIup!%(P;2k9i)xBW8D^7>Ot^E)^x)RzhyoO@;`1+}aj1Z;SStaL%@LaMuB+rsL1?S&_;EF-gr*QeTuL#R?r>8OZS=TUC|JX%CZ=n3 z`jeG_Qxo;62`;F7J*p;8hfGxI_bsmwXB4%laA9&G5*N1KBNfuLLy9V04yeBS&odw7 zCeV|IEY~8-k10^f15j&qxpu^WH=0sMAFVpUo{y(u<0^Cx#CBII=YY)XNrTPql)pt- z{_&lWgj}YT#_}-BlmkvFH;&zao?bYuC-fxN=6X^Ge_I!8{1iZLd$q`%vlJ!l-4D&F zcd}ru*E8iTJT!Gsue^yH)OklO9Uv#w?lyj1#M+hGm9aYgQDUuRYb=?uUc$1P8kN(p zl(qES zkiX5MKI|+HfP3{`QrIS`t zNaz@4@kk3D?V@a4Kb#TN7&JNTxsPWxzah5p%=$h^LxDj#XyX4Q4<$D6)l;SG`&`+? z*G~1kpyS4#)vk7^*Oi@4+p3R&xTmy~okAA z?b|uGyZ$PVr>kVg3I1>F4#)uegM9|VM;5e#52T#kf$g-K>$+wR&Lh*4n7GlCnD`%b zF(CsR%YDFRbS)Dr7#0Nd4yJ`pXku2FNnk24ZkI?U12LN#%kI(v2g(w-#3653<_V^d zBBG0NR*kC0TURv()O2SBs_~BmO#6m0_jkGV6yF(}fjpw>2mpL5fQR@PRpfazE)(L2YEJ;;TLGUIz~lqY zO%XTlO&ak@tx2N+Nrj%o(9NF2(EnN{hVDUC;bw}eFszClkBoF4@5c#i^UVr&Fe+3d zv3c=YS1NC$K}7mwQF^} zghC=bV7q6}?=r{;H9yleR&rmt$j}~T;JvgWhxyo_?lN6ooYHc85*Z6UiHx^0B14>J zDAi@gH!Y72hv_JVBW03B1Bbc%oEn~p+YAp8aomNq)0|md7*RG3@%9NBHefNf5*P8y z$n+6xZMn8h-SrbEZ?oPtjKmPov1mvqE*^ev}iEdA?YGlCTg`y zce}oW$(|4BG9XD0h5Un3-MD*~vI@v&ztQ7G`!0=Uzj(-Ez{Pv_4`|<|t1*4q2v?6* zIVP?JBYQVr<|FES_qQ%^4F%syr@;9xe1f2K967=P@C^X+i#ZYR$6nCl>c;1C>c(`1 z=Z^Al-!qOAjdq;yYJF;K(v*3fn61$}BnzvQnM57h@r|Y$wd_cnC6Q~#>fh8cO}KwU&6dMonqP8!^LRk40M@&x`|)!eXhNR;G*H_gNB5kgVjaBUh7II4f^!`elJU6~x8uG62KVg!Y0Y*M(ufHQdoWoIrV;Uo^}97%Uq zIpdEy1(szr+Ga&u^WEnM2(c`?|KZ`9Yi^LmmwFZLvJ;=9Nki{kVbrA};H9)(@qSf9HFl_v0+ z5Ec z;+!fWvnKR5PF0ibPP^$_u9vp*h%A%lAtaPS>~xjw;`I#Mb2aPEqq3BinTh68aDqN7 zOYqbCtSiY^#0%Z{E)i9wM@@Lx10gQ)ykxND*+CE{EUJoTH0jhYl6n$Ki#-XYf2}(f z(@oHOG2N^)Po6Q2@Q4Ox;CuV#^2=-TZr7}E4mMwQ;T2=X!4`IGY}9PRUt;^@S&WNmv_T}r z3zqI3#zNEbO}0-*;`>1-GPi>^8{s=a26tx5-#3F~n?<;jZZoQ6&+-$L7h0n7xf5g2 zb!RB@;pytRTl=F{m_OE*1Kcf&kZggTa%o#FRyQ@Pbaz(iCQPTNr}3cmbSg}Tc`&578~3UVm-r z`pWWa4McfrH0D;8W)_y!;p6~E+{)aU$*Z?k1mkj5f|j@^;A~Z`OYf)PADI$+tXZYN zWij5XYq4~ZJHh|W7aeK-`-KC{e+VpDIKLc9R~&_<{GqKks<%BYI7>Y(IRA&P1H~xWc&BJ&HOPV?`M+n^ix=;BffD`NBkPY%*g9yytUCv4<|>U`^C=9!y`%Nzu&n zZMye9t&cTnsnXskOM~nXzvpCv8gO-=`1zg&9CAys?vI>2)Hu(3Ruowe>Iu|`4H=yF z6mNHjMGi?#J%sF_%9FuZ(-aUIurg$4n$sN?QL;e76jp{!$~=*p4?>%Q%Xpw^3eZ5b z-kG_jh2@e4pxk4SGYyuU%_KD+bklZ0|yOnv^2UI+LeQjlVV}5x~Mqs|LN)TaCK0cDgT85%MGET2F zoI$kJ&DF(~nYqRi#pzAklN3x-fMDTyUd5f-^SmmJ7$ft{9njIs$f&+q)=))s*3gTk zK0ikcjD%Wk&+u>;osjMkC})6vk$~4-73|&LLOmlNz-vHqW>@9U9}uebX4$Iz0p-$a z#j)kPx2uXy)wbp8JHeEKaE~gi@9$05cZpzqY)X5KNGDZKi~DjAs> z&YEV-l1`W|>aTD|Wx0IQL4Ohn*CnEepSUch4W?+rbbSO6qm#jOxre0QVcjDIX$M_J zisz2))JVwPTKW5h3hdzb3q{z5zK{lJ;gwoE}sGm(T}Q zlL}PTNM7)2_?C&)tK%xlXvG{>;`6Fxm_UX9RM{jmuTs>1t#Vx!UOiBBYK3&!*K?ta z7`!?zUiy#E8Zm68puY3y}?;)?svE9)CK*5=n6bJt2a zOXYWE9R<;abtI_{5=@*x_pGx@2}dG04JRy#feuG=EpY{Hu$3!0w!JB z3+}w!_M;Yc?bn6)DqU62mt7g-9n&_=0?YG;VVpILzGH@A zoHX9fp>dbP%^vhO)M;gtdZbKMh4q`)KI_ zJVS4uoA7XSOckPB{(>LytJi1eO^3xhNf7F%Ip(fwku6lbkBmjS83lVWOU<9W-(C08 z+EnsfzjK>A@l^Trukgb8C6844uz-b3M*GTQ09o!l>68-anNR&y1PAwbi`@O7cR2M zf;TG6|E4=qWH zf+(U3@XS%$0S{-C?63au0sAXIw=0^eR7CWd3gR^2rFffm3zg98v|Rrxg{*J*zbe-N(`)y)KE2lrTZB&E_TZnh~k?Y z3Ljcj5SpGIP?JnPT<->ve_SIo+q0E{^$QirdNNSTxZ;#oZVuxEAdOs z9gjbW_4v}v+QQ7-wd_0v$>n=T2$f$%`Rv@aJjN&aoB_(x{Hq>U)4(Od8n}#?a3URz z68%Ceupn?Um#y|r^zps1H(r0qS(&)Gv}^~>)}@&@u17b$+MBP6_sKG%3VqY6!ktBQ zuP17C(@eDbut=jmtuHzCL<3G&_p?UEn))6J%frbbz8b_3&ZwidY$qv&o`^;~24#wU zQoTDNDrg5z$I}i*&+vjG83U}!KAJDfv`~ed$12RXGiKs$s>lha2}>{TwyOHyORv`8 zO$>pX<*_JK&7xil1m#;=f$jjICgs3T(pCR^>`O5P2Ix8v>=^6K` zNArbsf{CF9#WKg(Pv;B8u~)T02sOA5i#Frft56PJom6Ces;q(?wx5=NNGp$wOz~&R zipR0nu+!K8XS53J>?wQ^eZL(hk)^qcDfDGd#=Y#ZeEV&;nWBD5lG|;@8F#sdX;y$% z{85W>MJ=*P5SehUkls8*Z1N+9G4O5qFec|o=`{wf4RZi|D<8DuG(V*4|EvJPw*nCg zDJ&qzXzCWu6`oBsmdre^Q00(9yqTGt`b{3W=hMQT+l;JeUsHQ3ou+$57ty7D3!0}~ zwtY!mJUoS3L|01P?OsUn$W{U&&j+ERD#Cq8hUd?2?NGG`I(;jk%?soXO;ar(BCQ zO&utG7pgWT0E#Mcc5DcTt~M3Q<%`Avi;P62Vu}Jn_NA(_Xj7yY;F)h1V3|+vGD!vg z0Oh(=D*>(UrqggdiWKTHi@H*YFI{O5?qOq))r`sqIE9hpn|VF0@Z_Oj$F46P-c1jZ z!_)1NuHMM1wtZp?qG45}c$O!1p~I0WIoz4XPDI~}kO>lMZ>`S%YOJmD#wc&B&YS2u zq5=b5rKsnZAw5%)3~wRPW-zZq6iVlGjA8|94&n7=O$RE@A=x4(Q4Uy4B79QRl$KBc zSDHl;9Tb9UP+A5VD&^#^77{n zMbwP{kIcX9qS3wM+VUfNPTNX81b3Uo`Bk5nDlyyxkkm20#%L;AYDUQ2GI>Or@VVf? z+6qJcX?5r~ZWuEg(~j9&t<#19oy!;#F~so=oA4Rq?Y>in zf%xKsM{okwcLvR$#2?gmI%2mvEKVwL<9}4u8Zs6&!YBxX*z!>KNy9KcCF;iar$pWT z{KRXJj=DbkQlD`GM_oAY8W=Q;!DA=I3D_wlpO(j9C;JRz@HC@FQudz;o^WMk@+BAxa-H4C8508s7+N z48njONA!jPEE=XNo-z#M&Ye3(Qxw+G*fk8JX~2$S^qn-`Hr|8Y^c%+D9nc!5eTa!{ zJb`~ag+CI{LF4W7#*+pTv!BOH(n>lCG72nX3w|*8H$Jo4H?(PV5ttnVX2%U<@Us}4 zY2Zk#K%0tze!d|fjwH2Rj>4c}7zoZ`CHD3>+5mt3yl4a8KW{9JUp0)s#m_sb*N+&+ zz#kn2=-Y#R485k_z6b2~jA5MraGgBe%y!%|hi(ROVlKHmQSch`ykHM8mgiPpSswb( znUfbbZmcukSz>W)wU~LK9k)L8v|*h8SiR*1P0KSg`NaaIm2a*NedwfNTs*lnZr*u& z;N)}9y^OixC!tu{;}45&PKs`VbFPWsN44KL&7tkIz{_e|(=cmc~yS#$X==2u%dM=_x|U#1{<1__ARb zGol1uS@@9n{bzUX-1(UJ{nG@qH2&*`@dd;9HTwHY#K^y47=6ED7=6EL7=vF16Mq@I z^W$(e--n<$c`b6C7OTvy%)3aug&)V;nRQm)bIS@-#_|0lmFqbpZUo*-}-m|<{$pkkG%Q!es<~u z-}+Bp8N2l+n&hE*D%*R1Ma+`RkO)G)4vF8GC7%_)F-y*i-qbe(^30cS%$P4kY`1RKE?&eizq1+!VL7ec zo|>4N7~nt0CdVdm^6=h+T83Wm_>yZ!0j|uMvq2OF5uI6{HH`C514%8U3EU;3!1EX# zqMz2gJfz4b2}L64NP$o@s?_CjLQRiPTppXbR-M0AUAktjE-bt{X)dfwVvTWPz4KZG z!7h)D)daz&YtxrNu)AUaqMcjt6XxX!b`pp-X}aQgBBjvf(b{LrDRi_zp}(RiR4b>@ z3IsK0n=zmSo|MKWW*;Fp$(3#oQ1wr9)PT@nSM$vFgPHM@c z=kJO`cPgFW>q(YCmq#Zi6oJkekbGabV;KMJj**?v#|z}rr{Y+z71u^#VQkDBYp&Q}*`;4XW9b9ucQNhH<7} zr1fWE$4`j#6B2e{YmBFDjh&FN$3%VDk^jbjoOZBTJdS;exipTq$*|FV)-d{>GmO6X z(f)?^Hs=OE3~K~m=U`rR7`Ddr!R|_AwBy8;$*?n|$rU`x7P$_S*&u_+-t{a$mg!I- zn|R4lCV&jhWV_mlStQedsVEHNtnDX}C-bm_(DK-ARTC@@B4^8yyL~;iou&c}+wzzt ztA$AccA{!*v#?=X4SIvYvJt63ArBg*KtU49(&%lP5vf|yku;s#Qe_z^(DwFL;HwT0 zQeMz;BnWzBwO)B70ivq$e(VPcF&#eV1Ps2<8B62;SD#`0hd#sjlRo1- zC8}~Ev%R3@`g)}fOMI48VwT`7qZpmS2RkzPjVG(XW9JOx2zVIZ;7fdi=kN`zoozeh zMr=`-NJObTUf(5|4oi@h-r$ixW0eo~)AD68l^ik8+E>u3ZAzBF;8m)Fk3hBQ`i|=> zg2L#eXLDy?Ss1j`b3JCoip}#ibL_*Je{^x7pD5@IrxW%2O&lDB%xx37F z0>xqAC&!I<6#o*@+<1o$-P{%i7F_tB(yq*)ZQQ>QzcDSpL;U`?{eY3)POlq=@z2F3 zecUh%Y$QL&t&4rO*y@93|Hv@Or-7t(_<{}8b^~M?FZR1VDFjfu2 z_yDjl4C7m{!8DA4xpRi`twNN2*f0kEDv8Xu2T#n1%o~O=@YAOaV?kv8mxeL;#ET;F zC6V|E@%=Lpa)GGsY4QCm>@v?G$HbrW_%kH(-Y>o{i0|9t`!fLgwD`vh5aGuR<1O*; zZ$jqRv?n0{JMH(+z7!QB(i(mX8 z{_*{Q-L;$`{yujNTV0PzW}djb$I)qAoEkmY{4r0N&K^kKbA^c!#@|{DC^$x zNAbF0r8W*j_h=iYyu{t96Jj?3_c8qWDE@qe)Ehu-xI0&oas_qx2i7qSxXbu+34f;W zXBdAzh(8zc=Xs4%Pa@$d{CNWC5*lP}`xl4Ffn-yKZS`I`u>VjwkZeTHfsu|F50(#) z#!fTKibi)Xl%fz^2!-Yl8PMp7#f}YN;=+P$2foj2l>rJ0qT?WLtAS_R){CQNy(%D0WuegU^cfI+)k^6o}A6L!%myEW$|MEHnY5ByL-Ni zh-?bwV)L(F`q@2ni5n_Wl{|iM^GcpYHumFhH=6Tan7iA6_~pGjNEl_ zttwGlC7coQoE@eT!J0e~oyYctHi)ui92dFKE%{G$V8?aD;f7d)WhOeHW$MJl9P`GL zP;7x@2^>Iq%u%g@q#kpsc`T?nOJe5R(SE2H54~?&cBt+5fJ57|6XvPCu51k5Z?kxt ze8OZRs_?BOY=>&LQ57^og({#e`7Ehgj)RL;6+~{9H9;=OymX68^`k_j_ydE9B-TtS z89N0=PG)Sm2)HlnM*n4wpH4hriexuTF6ByOvf7s4N<|fjtV(IMWzr*SPc|;`b;B6R&6lOi1Rdl5 zr1a##R-}I`i0~i*OeQ$&6&@*rKB8^|>V8Wpg4>BcFfn1n`8EuAIL|SUq!;A`% zmNndgS)-|HJM`je6z_)B&`OtCSbUzb(1!yc;$oI_6lr{>!7vDnhb0xO%=9y%C>JIctNqoNzTF=>%H zrC~YNst_;dt0H}9b)|TZbR;+R{RideCs~uL}2vVyu#Di8SRl{<0&#&b~?KlG?f2BR9;@I>#53ouhO~4Y-0X8z`wEKe|m&KUBp$Kj5t>L`1Z* zQY1$+*kCP_r6@P)sFK(UM3&=r6iJENlu~tlJ7{a#9yM<{yG}KX*p_=+HcwQhbm6fo zGhiHuf_9*q!_pA@?$%bSYypFqMTxC6Hgc|NH{)$9N>@%SG;zBLEmxrmZ8>hM^C`3j z|8u4PqvLVBT?r$1*GgDs1*Q4|dnb0cGE*;(3#$~==42~f%+Ou@yP&;;bV+1wZF#|- zI2e$W04ger8@g0CFb^ruwJUs+k_1t%{7@+jt@KGHVeJrMUsa7b1Sr-RS$kbeNE|XK z#7V@gwyG6VwODILzgHA+?TWazDJcNvNut`NE88}UEEbH~483>wG2Vw``nO6Mk3+X~~h< zRkRZ)n$ZqJ6T{^)&K!lKgKm&i+qaUW+Khr7O~OGP4?^ZcqVQdXYzmZ@Il3tkdk|Gy z+-dSzs2{yU)hvgoM$A^u3P7uwL|bts?li@95ZO2cZ!6upU>K;zz-e}38Y2lw<`Hy` zXT?k@STd)X$g>4m1`8z0G?Qw`A~)RD%{Cyh$h4eY7A1&buZm(>SGkQii8?ktuOO?I zm^R^^VEMjQRKtfa_L)Lfh|AD;GB49TaG4iGRy7I2RG?#QD3$MaR7GF_O7~gf=FBjt z1o|H9D3uwDC8f8NaR7s&B7=$8=x9y9i2)jv+>^M24yI+9zZ=(t{oo^lJP=;eSsX(w ze`5iZ`$@!*`v{*T+>^hBfOpg5)${aXA{N z*4V=zLFv=gCcXdGyPrY%W4H!&00xnU!7)_uVSXVG z0gbA0)AhwQHTt*uXPQAt{GUzN=Pk}`+&rMg?6|dqj-SLh?FYr>0ti_ye?tf_i%}sS z6TiVhQut%sKQ7WSwm5&q2W`D1e*f_i)VVbNt2_!Hr}?j7poAo)8~RUG={T*b#!F^q zd(_~j1A60oju_Jze}*0oSA*qQ)}{`$p0Z zsWvZH+ey@x;Wk_*IA5qy^s_oD%-X2_nY8+RHnkPz+B$`{9--UV;dVGZj=!U>@1jMs zYl{L14L)6LP~=j3AJ4US8tomcT45I|Sz(?^R>-OJX0E2QsOd2gmSMXZ$J>tRGH}1p z6?Y8~_&;03UxT1Nyp(JCVYEC*qm3gYH1~L+Ipm=JvuXWEq6)LqjE@th2|gX|yJIYk zPxKjm<9){Y6TF47KI8nE8(Zymdur;{R%>*8uhwUrKZ!$77F8U!TkSK>pQ@(Eg`<7O zc@@JyVy#i~DH)AAl|I6QK2zH7EOKOYR4W4{Y$x>P)Fy4n={T&gorl^1z&3MSWzWN! zs1gfmD%QM+#euiWqN?TSMs(Vn%Pe8J)s{p^9@sN!hpJ9IKu}6`NF!9~Shh9mC#Sw3 zIw7HDwk=!r9dyyMGCq#Eyv$w$G7sh2o!GTA21s-(&AAoC6}tNZ8*LA5(2g6P; z2iCUi3WZ6Pcx5R>cm+Ni4}7KI!z!Pvg$(G~dgSnNO2^w)nC|1e% zg7KII{aZq0Tj1AJWgZwm#W9IG{*KI&yefIebL|wfZ11U6syKznj+@A=fRjp?=vKg0 zVpol*L<~8(lT$44z!_OuU9y`ZnI?(si)2ZemmZB`PbDi$Znsmu(_0DC<4p+<=j(RE z>L>#b1VP-6b8{LhVy8VN@!rnMq7QR@|D+Y6}D6-X*>V`j*DuGK?=AF&;N$Km&cj zuhI$Z7mgUulxEkbYPDMRy?UM-C((XoEPW9gbb;LZW_Us1%BW%V?HESiw-`p>XAA>( zvtRnF{QKk^hB0{buNlT*zXw0rH=!kQ{hgG8suS$_^ti`uSinN;kF;zbiLPO!;gzj0 zjFq!0JXfoD;~A;dh=sxEzSZ`yNg}Gk`G+E^Nb+IgAyK>L0PaJQxVc+=A4!c12>kV4|@PQQ=YYRRQX!1AelfS{AST6B_ zESJCWEn#qeCV#{FDt`}a@UR%k^s4q78*7<9t^LOBYnhIdZ~6PG_8XgSnSMk2eN+3r zp#6SP`@N|B#`aOx^F7+{&l`sEoap=aYU#LLBjLYa`~3sj?;p~Be^H~u4{N`_r2YO8 z?e~vrzkdujp#=^*LR9_bw2oLH6ExwrbG_vY4OV&n+y$7|OMG@6H1?a%t z`N7AL{vHWWSmCby;1iUdX?++?m`8Z)st7f45kYSkDh3{c}kFfed4O5sdMW;Js|t4Q&51+0RKE--XIu6 z@KgnQxHjsgKlFS-m8zosMc%NZnoy@Hxx{FGGjl1=PQh zP#GM4uZTl#Fn(Xh;rB{#z;shM5Wop1PJAni17@DW;rF0&T5onDb$Jx~4}9=F$nPUl a>@T6Vc6=wZ5#q`$S!uQ^\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228055320-Binary.backup b/MikroNUC/20260228/20260228055320-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..72bcf07a8c7761bb50daed8ca9d042a9e53cb22b GIT binary patch literal 307416 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 a*k3|z?f6b+BgBR$ literal 0 HcmV?d00001 diff --git a/MikroNUC/20260228/20260228055320-Config.rsc b/MikroNUC/20260228/20260228055320-Config.rsc new file mode 100644 index 0000000..cf8e6f5 --- /dev/null +++ b/MikroNUC/20260228/20260228055320-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-02-28 05:53:20 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228060001-Binary.backup b/MikroNUC/20260228/20260228060001-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..26d1db85ac7c5322ea22cbfc807355b0fbb88e10 GIT binary patch literal 307416 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 a>@T6Vc6=wZ5#q`$S!uQ^\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260228/20260228062001-Binary.backup b/MikroNUC/20260228/20260228062001-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..fd6c801ba59306282fd836800c3203fbfa2e40cc GIT binary patch literal 307416 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�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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260302/20260302143114-Binary.backup b/MikroNUC/20260302/20260302143114-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..f920b94eef71dcfbce823aa76dcd347c099dba21 GIT binary patch literal 307416 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�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\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260302/20260302144001-Binary.backup b/MikroNUC/20260302/20260302144001-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..cfeccf7f124a3f8dfffe437bfbe77cf95b17bc32 GIT binary patch literal 307416 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 bVt)y>wc|UPjSyF6$x5?TA+JJF-uQn35QIT% literal 0 HcmV?d00001 diff --git a/MikroNUC/20260302/20260302144001-Config.rsc b/MikroNUC/20260302/20260302144001-Config.rsc new file mode 100644 index 0000000..9db5d4c --- /dev/null +++ b/MikroNUC/20260302/20260302144001-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-03-02 14:40:01 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260302/20260302150001-Binary.backup b/MikroNUC/20260302/20260302150001-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..1e1093dd9a764a4d43e4ecccbfcdc85335152154 GIT binary patch literal 307416 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%0A4cu(C942lkY~M@n)~VhWX2M8~PZ)(Rk3IjVuM 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 b#r_g%YsYso8zHXDl9gtwLSBWUyz&16(&s`S literal 0 HcmV?d00001 diff --git a/MikroNUC/20260302/20260302150001-Config.rsc b/MikroNUC/20260302/20260302150001-Config.rsc new file mode 100644 index 0000000..7939bed --- /dev/null +++ b/MikroNUC/20260302/20260302150001-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-03-02 15:00:01 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260302/20260302152002-Binary.backup b/MikroNUC/20260302/20260302152002-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..1333666597dcbc67a12b1ab71ed27ae002d4d281 GIT binary patch literal 307416 zcmeEv2{=_<`}aBn&M{;RrHsi?*k?XRDYFzQQz3LlWXu#vBBV(w8l^%>8Yn6nRT?x< zG#V;O%FuuY!gsB64ymV}r}zIo@B2RA_wQV;z1P|H+I#JL-^1_z-D~fYa%gYS!$K?& z2LOapj3T+AVSd3u6951x0015cK9~`0kr8bbe%qdi0sxP~|DhoU00`oS8%2ill!Zq! z5v~UY2M1+^?b!eT6JSro0B`^W#DP5#3jhuPfJOm;5(5J$aWDW-U;qz9zyNM=aBvV0 z1~h;S7|_55GW~*N`DY%$!Gnsx-Q)#V6B-;5?ib`^6v6TdF=F$4B!!n{EIct>8v}cy z6c|9s!+!7_sPSMxPie$Pcp5Pdm&c3<2p`#&5MCXJ8|la9hB*rl9w7r5g#BpF?4}iBC#RUN63joRw z0I&$a+Xqm=0DuqxfEXCyUlY8xr2v3f0KjqpzzV4EQ0-R$c@ z?E?T_R0dk5Jly6FjV=Iw4TAmR0ay&Tgu-3J;36CVJSPGGTpAaENC0q|Yyg%3fU89S zhynoDiUA-R031b9D8m@oZ5cdDJOF${TM4)Dz_4=20H6U9;P*d>ZlvB!{1v?+^7V$n zqmZZwmt?@=khunA9+~+=y`lV2Zz%swy-E72H%TW(7)>#}cpHJyfbaB1B$6BMOAwB_ z4FesXG_WUX4-Vj!)dvS~;^N}s9T>n@k#E%d7fpDpeJrm z6doS+2AVp5Ke>_GUh)gtZs}n0f35AP|0lIwAXokk7c{SqxZ!1ga>Erl!EAqSs6kXH zGuj|BfEyNO09D|J8lVbq(IGhn(f=C_5cu<-YQP~m1rfdm2=)`keHM>16d+*`#R_8& zTw{Sf5ypI07&kO>D1v^!1KiFIWCr>1m~1Ya=L5q%jCU~D!4C|EYQnY^f4d;Sq6Gn- zukOO&Ch$A_0Ivq@iLmF8&xCtGOn}Gm{|%!&$Cn*q#18P|28DYEhlKkD2ZcfK(mgmh zXd^sd&*0#onXvtVAH4*hO8@{H;W*&+puhkQ_Jb!dK?9&6heYvs6Lc-?Y^`QHdt18L zTIvns4k^Jo{W#v72tSV5cZY$e96pRJ5`_?k4`Xj;@%1RUp`%Rs?f`I{@Bor<91;_B zXE-=H&o;BS8qw7^I4nGf8OVkA#wRp5A_Ni2oGiRPC^?F-4FL#2*oN0i6}GDZ0OYUd zM!|?9xDhZG1r6X~Ph1)t3PfBe05q_nTqcL|qdsWZr&HKRW@I0cC82)dT*8k!VPL0$ zLH>#GBhJE$2ne7GI`Bt4JTffoP|xN^TAXI)h(4k$Cfh$E1R}=(HYYqdg6#|S5`L^l ztgV4PF$e(EVgNuG5V%?xsr?~ngt3nc01hVx01tkFK^F#ZJSqe(7C{LRh$J#RasZd( z9UkiE)rY=M10G6)?-57#fye)0AN0@rKs)|nAI#7Dz_EYd z2Mx^<`?b$dPR$Gnf-VQT4vx?*z%@tcW8tlo1~6q2I(3*vKu3W`^D~H{U<;Ew0P{yc zfTtG5`PU8baslA4H=yl_3jjcI1ep+YqbL~w z_*x|o07?M>=w_f#K`8@(8Y}R-;1&QVRRBz_`0|1&T^n^43@M3f* z1HPwr2LOje0N^29`@;YD!Tbuv&*ktd{NWcY05J371Pc8l%)nqK8VmsLxi&x3!<)i% zOciEg{214b5`-+c=JOl(R}MRB(XS4hZ*u{k00A73?061l30LH_;O#!$K_pX9FR`dG?!TH{cc-0B*vyI#dinpGk1{$#CHaPbmD%9nrQL(Y74XwiwYiAJMiS(Y71WwjI%) zF`}(IqOCKcJz+#!YeajLkfvE2!HwXCM~863qJ(ziEM#P$?s^K_(A0<8&>R;Ew?mY* zK-lgb92{f`+kJzBgB)QSQX_0(yMJ(SFhJObuwdwzXQTjdM%feBV4zF7fCeBL1Hc9h z0BIP3@lU`2)J68E)x? zi#`;)|351Mp&-U~4m67@z=tsv*2aBX}JM3g8t8D8Xnm;0{TcuUZE|$&gR-{M%)U{$DFo z89u8Q#0@tPvYvmxa54Wp;bQ+Y3M;e3FO@?p_IY~Rq} zpx}tGA^9%&+vO|r&y(+eNO`4wgTuo@f`=Ug>+g^)YD6T%!PxrG6R*gBMt$W%*ozG! zLIQ%BoFVPy{2dZTkCZS(EdOgItNBsetOJ0O_tKUC$26Q;p1ksN9d@Z0u8b^fFV6<|+Pg;}#2T;KrE z5Qp;yjKagCoe(&S0umySiV`sJqOb+oTQr}P;FC2lqvx}qE42Cb6b+yW)ADg}p#>K( z9fB-{hFBOk)Q=f}#QoCg3BPoD^uK(10wlddnVd+D5x*)l#8!C;g$37Mz@9in#0?SH zQh?8A@HvwCXg-;Z$3TG$)7g;n7m!(enx4;R$-yndq!vu$@z-E39~u${?~;Ix6MSGz z3Z4XhAonB%1T!XJZ}iA76XB2rvNQ+?_VF7g+#nkTKX7dzB;4RU1wP+CJP3XX1x{9h zoT5l%I0508$-?{sy~DWSaAFF-XaGO%{H0*+4(y4Lvw*W>Aej%VT(C;V*A7Sw3Ff~5 zJd_w718IFe?-M2D^#Gnv-@(CXK-xkB$MXvfgsvF!84+RJ&><={Rd`k?oS`<{XQOaC zS5WFPdMN;olz#VI>FN3$z{pxC=UXpg(+LAkio&+-U$n z&{$Hm*;?<+mz#|%bQLxA<9rsR-sx8~yrPm;UGMRVRCOAq4gf*Majfl|qwnSS=R0Iv zqpgkAfch=M>l>$qoU+V`(>C-FV6Ev!)LKK{zx`ojhQbSSWe^XDU^-r5*5B| z_{I%uT5tl@fQCRe&O4+tA{F|QY|>WkBd0#fnq{duz37ExdF77k9{DG4HV9-B<)zj( zbw-=g)T-Rn^N%M;!qMRD{rp3NXS-OyYQtaMELcSwzFFT4NCXZD`*lDuCuEXUmiIrS zx!Emv%>gF7-pz-Sbh}SX@!QtZD%5YOY-q;Rv*a?A3ZY!dZc{R-fK@PTkZ-Ylj+ zq==yU88Mm6A>MeXCJEQDJSZ~6)bo{+ukw5v6!OzD%44(?OddZeZit#o!hgB(N*Vw# zlud_(2J`#^_)Z3Xo(feMuAc&Xq9ULBhn54Ul#Lm-`~j4<(9ED3zNxMAT?vR@Aw=F1EncHb64$-=b-uqU38fJEkL{t_Nr=+0545&)D* z2q;ayOXQ#DlmyVg8iho#;6yr1NCXR(FT?hIZo6Uh5D-JLK#h(b3G&CD(ALwBRc+ zL>sUeEhzfHdJrBp3Vww*W2hS}5q;AQ7GS>bh92&Q5}xf3-OxYi25ZfNv!Q?14fAa` zG(VsXcf=|aqynphV5IuWqy}zQ(l8!L0Dv^0kOb5tBmuQ>4+f1wqh&!Z z+CTeEz%un(>~b&e{>>{8aZ#Lp@{HRiSPTX+BuF55QH%>#R37c(M36!x;1_XuEW9d$ z3^EFS#mMtdqwZ#fs47VjDF_20A^eZKk`x(!B@#H4NFCQ-wkr5T+j|Pnr6`2%| z1)3NZz)qDLEO>UfV$tG4-#*-UttD@F*T+cSwPkF0Vb{jG`xz;fU)G^)nMCMmpZ(z4 z{QHF;G}QazE|Csa&?197$4sa{t8PMPPZsH!9k%Ggy=$EHawYaBryI`jjb2MR(>bkg zOpZBX%D=Yp(kRp*7K=fnL=kCGjLUd=_+13SpiqOzc(`E{RuQX^b8Vt~>R!8Q3j51W zt!u_dT)P}xN6Hc70}u`xiLyI-Dc0a_j|=)xw~|Yjd*7=Ucf|4!r#7>1&pw~7B26(? zG(ft>q!^gyl%#r{JcUNac(r6NOL}sy{?jE&_CEXLUhN5;6+H>tFQQvqPNpK%O4Q;G z-3vE@H1?(IOnx^oWinra-+-I_V4B@xO2V|L?bc12pk<0BD$U31l9R&E!y6 z2tuULNCX6-vYAXWiAf+5m_#Cn&SlULgh%GF7;GM$LgXPtCJmu8nG_C%N~Nv=fbc_= zUJFkV1%QS+lZ+6lEGCi5qq1piBElgfWEz*krBaww28oU=hNw>H@PgqSGw3e@;H)bb zCnvnXNn(XgaujedvGnutv*3n?tJ?;#<$;5X$&w{Y3^{&2er#@NxFI_@a4hto!+Y5T z1hbd{>iiQ}nEirBEqAhl9(6^LTeuJOu>5BU2JmR;R135OPL=tsQ$-~KfHzHs{ujDa z6m+MmLn9Cj0G{8%%#a-#ZWzK1^hSog>~Rc|fH{gJptlOVtPF0-Q`a!Q68i>|wE zygCz+62xLHD8=6mrF)DcyID^?or z@vV@cYeuL90zu%Jp=%})MtuEG3?TufIr73$A^?+sk_JcuN*tYlLV>0!&tyXz59HS5 z%sV(IdxON1wCmaXI^}L}@j&6#Z=yEm%|=c-eYCjj2j=Z+TCdr#O4Jm@<8R+qS$Y1+ zttpGGo9^?jiX4yBQQQ!drJ51jd2&V$?(zMjOC=ei+_;&ZYG;%_6`bqTeGneEG-|tB zl5fxgE#j>6voEx|2R4VCUm|n<3+hACqXU*Q^NINp%J=SMpR;MwS=7CQ^vM>taBZ!3 zv2o)0y$5I7#ZIeo@D7Od+B1u`F{@s)CGfVw*wjTg25uc!;3!@7(90s8f8W_#BVk@! zaMFzUShDubr}%rP*Uz6`qS9)sn;r6)fNl7AO!2*)_-wHQ9Wzb5O5$?TE*;fD!$&l7 z*a-8x*pvKcu?N#QhvIt2?lkXhPLqntrLD(I?zkXoFf?gll@Y}iKi=V6{lh@%-^ipL zoFOkK-rHcA>EKw{{p1L?CpsFJGeP;wtVxL%3`*}^9q2Asn}6d}VCK^Bm)rCTWJ{Vu z_Uyf7m$H5Hx{V=C1=8crZO$KL-+L~$uqNmHE)V>>d#TM%-Kp%}>3Ma)#ucyk0VM_pbR(liV(tYIPXsCRk02cHT5`+tU>@4$$7by&t_$vGGvrs9QmYES2a+ zwvV4#P17%>I#n6Z5&dY`dU>9008>Nx9`W_%4i6+2po(J(b>+) z(aFqdh8dAUB_c$`!i-=*_yN+oiA55y*N_BEp%7_F_M8=+*M_L>Z0Drz=wzlY5Rf{Q zkh+B#;V&KX&5trHhyAD7!5wLit`&hgF-zrK*SzcgeE;RM4QDe7-Y+y89a1L;dUeE0 z=FvT3kImh@IAhczvvd!NN^eZ>>56j`kO9{>m%C!OHY@Zf*x$&Ld9V1oK=Um@QA_5C`lfmp5nwAQ&| zs&jL^J8Z3;<0hw6bjxRM9X%D(x|dP!CrKe(M7T0h@2K9L*y(ecI9M<#nu(`9e*t zG!DP5)ueZ2oQ>aJ0m4c^B_Ii?<%ryHMvp^8QK&&Q3XDkV!;@BA;9Y$}Ypgn}M>~ia zf3D+}(l@|rwx+YXaz;yYP>XbLZ>d~|sL}?;ACMcLB+$kxA_}6oNunqb5ityExP?X{ zhuSCOc?r(ppun+!^1<2jf{fXVIkinLx}0{Ug%`9a4$9!=1O7T?D(Bo!F18_1n5Ey#GS)#2BZ7!?(EoWtpOxYaX~; ztm?40bM-!4UQr^VZs>MraAwaQ{fC7ahp!vXobn*=LvV`T7i9W`#M75f#%vawd~}t6 zB&h?qI39D$dR|)H_2i}WK*OiYr81%Mc&vBT)+|F}L~7NJ`FH0LmeWx2$9REyV~cqB zz&k-{-KD)oD20jzt{l{(*i{GUPP^B7S_dw;qLUb3yL{ccoSlv@ucWlomg)Dsb#bSM z$~*+}Rd!)@2WgZ8dhvdlk!Ko}W729XtKRrv`mydBibaF3r$4Dr=xOVA+oUBmK|e#= zu5$0jmfDktR)rsb7nrlX?(@B~iKe^7wm}FA9qKRyUBu!u?~uOv?dgb=-=6Nbr!)HP z>Ha_PbYHPKn~o4EJO+n?|S7SPUkGPGeDsG#Z0OVo+!d0*y>1 z@z`_%iG#4HL<*C^$L2qZ)qHIJqZlo~=4>8?#X+b<7KMrsd1M-sMW-M{Hj%_;^AIW( zV)K6idHoETrwhqWQ6brh2Tmqtp?*t)gP4-Q&culw93CFVVFqxefP;xmuqBhjiH3Y9 z7T5-{4JSd?(l5UkpO~JHS=pO?Zq4XLag7p}PK;3yseFCu05*M!^)jMV7vO1LTkjW0T_>x2 zvgX*hg~jw<^t#(M4c20f;?vqZmt9-dS2)QjcN5ERuC@qstY!SV$@vyrw4NL?j^8m# zuVP&OD^JxESy_lUzo1? z?m9pD<@|zE-qv4kUsl0P#kbiK7Wi2oe`+HD`>>SvhteIaTaK*leJ$k~??@7p@zFi; z=EGSLvmo{I^vBYT-zg~{s&23IjK24ItD6so`EL0XQ9^{lUiDN5?yBOC`!mlxd}UN! z=iXTrzAmhoZvI##<`X*NRR6xB2S+|UXq3Ot^_{J~Ck-db7NiyGtoYoz+x-=7 zcfs=~0mqY+c9}ey;1Io$a^D-hz4aldYw~i1FX-31Zw-q1D%EMG(G8ZazvKMQui2Yaxzr>^ zyty*YoAIJ4qO2lPnRI*dTO+%}AB$ezb~tc(=S*kOin!Q&IO(Qw1Iv|89rF56t9Z-; zFKPcF&%bzkBDZpBN>h{Nxdk6zkL%%A8kJi4^F#TSMouPtI+YJqf1CN=>5P7x`EN7- zubKH*oJOV)$Owx>B-6Mo2AfT1Q&?mk!lAJ!B!ofW(ICNv&>37Rm%^lyxI`M6!QqgY zY$k)ipmRA)K2H0QcO9-OqY-}H_?N>p#9V)j_d#$r`d4TW2rJP->>y-IqrNFX&#_Yh z4kj)^eoMLG!RpRjwr@}{oYce(Q+F~nGt_|9Xb5j20@c5w9KYb8ujp$WL}|iZoI@kR z!nqvv+1&6Y!J+=YRGnU}G&lpoveksTkdd$q4`JC<)t|z$@2k^lf-x8f$6z2FgMo$F zcQEWcgkh(V1ayu7hGDRl7e>Z7Sdm^n0*B49BWNP(0-rYKr;;M*Alh&r33=5&m)Fq2 zF!E!5Dm6X?qZ1G!kw8RfB$~UD6p;ZTnDFa=eSClAm7Duwb3)55zP+xns>dHS`&p2w zSXrQsXWT~*gX8X3=Xw|968AG#od}XnzKfu@etO_HZ?7`La}g){3d-%!RKiU9vb)&3 zvvgb4y{Cv}-?R^_>pJ3a)%Bix-j>z9T?M|iTFGuYRd}5F{7QaDi16ehh20ln#P{)zVQ4A-IjDSGHEx%>TYhIkA8(KBsX@INIGe0S*M+eVq#Lsyo zy6?bX2Ce$wK-2M_?FLqfYhIY+AB3ZgKCXVa{nZ(rTATG{Qr6>^R4L?+E6pWb&eRRZ zkOxU)ChmJB6@GHs)+>>%I$Lsh4bP6eH}k06=DIR0TW80Q zn(l$o+#`36H(z$<4b0_YeSL#1N>3TiXJ*ty>g?KKAiDp0JL7Ia-R>O{I%tYsk!i-u z&#jp*DPyefpCtDzzs=b3i2iQwM~BG}d_iw9#1ldfG6cSU8~2|&>tAv{zm5C1asSth z`zz$4uqkvhmCm71coaI9%%E{;WDMC7n& zR63hXM(A8VvXI}<@m-NG+CS_wFqIQw$dU7V~OogH1AoQEKlE<{`Wtq^MQtDw;0 z1)SJ7xa_Zs*ek~HX7LHJyMqEkOh)hm8gYocUg-Q3c@0gr9#O%bG(02&M<=rpgqUA& z&{s+ah4tKoz&^)Qgj$1l4c8BMzWHudCx5pcB z@b$M>@4ji0-~OShy#8HH(ft^juIwb6$BZjyjK>sv?>`&6D~D}PUso>PSj*zn#pQ^;OHp2wraAS@fc)E43Nas^tEJXHpL<2t#~L^HMzVtQ z^fRP^V*IvpQ+aIx8b8^9s;*;tom2sNnBg?1w@=%s9QM0X`c9Ir;Oh4yDOAE8; zB3^QOQ+IG6e74_J|8)yDH(tIf`Q#b#$j!}D=0;`stnD;$9gwW{lU9-L(w^u~3j7#k z(;H^-V)>|jydu42#6-5s>dR8)o1Kv{@`q|-X?bm)#sQQCb!HFb9_QOiJbAcc4Sq8# zwS-rtopLMjRMGTYhV&zJR-2q%#*deVc z2H-r!B^+=2(02aVxJ}fSxtm6HO^h99uXN^myT!!n^JdtTyA+s7d+n?Y52+n=a+p)A7bALHa9J{R&N;qR+b@oHVn_dBwAbJ1^{d ze+1)r@PWwC4Qtm? zkDiwjxxILO%l=@sfc=YE6%VUdhDyHkkzFmBDQ_1_esbpC;wJ|eH#{p1ST|M9ll%DW zJh>AV{(~Eo)H%@a=t=lE!Ac(yc*moW5I znUZj{eWg!Q?Y6n$MWx$UtR9Su8nYmJ=0d|wrbp~(`jf9;WnCNP`H|{T`BYmQRopOE zEOQB%UR{5$-K4hn^z@ra_k-i|4W5*uKlW_hQ9^lq$)|AD%zWJ}t<=E&+Eq!hCq1jF;l%s8<%NY3 zPc!W51%^t^= z`4ws@1dGm;@ei(~PPJGxK2NzZ)vLt=fqp(wdUtS`D1|X+2&@10|NoIt_1pjd z_W!^A|8M{QU-AE6(>X4UL1Hsl2$9F3GnoVumq=if2t*>C$!4<yAv`vd#AZ?mOge$ZVpGWomqbBG zL=K$Q@N4)UW^_N!6d=JqGP8gT`-t>INU}3U|K2Idq`%JQF4*_Zh1r}br4MFvg6C!> z_^F(xAeH;>5wD*=H#>f4&aHu9Lb70%gAM7s{LKQ5B%r4w38)HT{wCt$dgi@XE`@R_ zSNdLoRp`ivK>zJeSlN*HNf`-&c^DBs=LIJ&z%LZx*Z;&2e)7m}L*Ap)Yfee@NyKT~ zeS7X)SQp82>>2Xw#w$C|RA+p6d$U@ijOj7gdU=+??#@)Uq*A+BNKaLwq3O!Z*6C(} zQx4bUD!5Ujc3~_!W#j`w8;_*q?e#CQxb0J~HHaCP(=_c@>io$g@cr?+8M&YLRy;gH zHM=Rx_G9UtnRR94-NN_+go`GC!)M+HOqZK^$AEE39KSWJJB7L~Mdx%&%KAA;dF;327a@EaNe3VQwH_Mj04&*LIz{i&=u^#|_RW_MhzzhfJxggSLCdBf~=DU%ND z$X`=&2b}%n+_d9`$Fk!(N)RAIl^r5;p&AbX#NP@QIy~*2|FowK>9>OYs|xlt0+9$z z4wXu#^XLSGOd!$OG!mUhVsM#c5)mPgNF)Y{OJWk}Y&Jq9GN@c0gT^K@*$gg^N+S_C z2tNY-$Z|$RAPR*-p|aRKA_X3nLZYxqOftgbP?#(-g+~1OGcPuzf9aW*hF_gorwklS zoWhx*JU?y#=bHkrV3OTrNGN{Yfv;v?8O6VEmYw9kKFiKvcv%0^G`nZ8zT1E#poL-S z2h;2}e9I&L;xs#LL`%RSjvF4>Hv$#TxFaHnfJ)T+y4zof^{=Pg{o_XbS4E<;9p#uW zA2xhJ7X^Flp7Cf`bW`?84AWKllFf++l_nI!)fON3`t597Gqzt|J+s($2~p3rzqEZ_ zgJy4Ny$*A0=Lh%1_MkDPt0&hddfW@|^Y^Y;y-&t*wY5w4sfckcanGHP%=+XKIuAYO zlhR_hHdS4*@QPhC&IJ^A=N5KxXwjQ4v|D?{JqvWQV;#MvCc!>!ysPg^G}y)rubP-( z%I-QAx@e5l_R88(5jSalYgd=My<^3BANS@WpYl%HN4l#ux{1cMvZD|{Bo&XE$!V` zR_zZo+0UonEt4dwWH9j$fCLhCf z8JLNN7Q1E=K8z}nJbki>7N=PTaz@2C_W7Tla=9jY?(AD>-9BPtu1&RGDus%znEx`c zB?(d5G2ybzQ|!m5@8fC@iVvEPr*)*i;JC@DFQL~Er_tjhwuJTiZYa8OTdktKH*iSacGDKp}HjEEzS_{uChm^%T8w8T+3EPk5?cOyvwreygOY{WoG^Q{ z*#;J724+Mvnx!?#l44~=l?DJgfPF_unqs7~;pHe%xm0rYM9+{xz2yBzY_5~CmL^{Y zj&YghpHWYVYu6qLD6Ie3p0WBhR&n1Axp$Ta@8(pVc;k$0SbF;t`QggOS`L?s_3P!KV zEnt5o5jQixt$D!H;OP?YnI1}OO82bj*)`d0Nw&gC(y}et1fRPe)0VL(bBj&K%Ze52 zJiGU7)D&^a+SLr{iaT>Zy{ge0v(0vY{X5ya6WZ$5oOu*wa!BPt=fLuTS;le46^x{9 zU%fXuzWz{Jw1)kwft6<3u5-`MyT10^#O?-#X>a_)2O|3C5B8j$(CGSwt?@zX9f@7r z=8zfx>Y9Y@aYjwlWT}Nt=svYeY~Od+wa(RG#oQ_nJlVO*tkFI%u|!W!vE%ku=>g}J z=AN00ryA-XjWX@vc`dcn>z-M*{*qxs_zeeKS84p1`(ANjz0WK+o{o!{L(rIvS6MM- zJ?5|`$#K(EMqp{<>*rgpt;FR{+**N)@m`r|v1j_!7k%uz3j%O?OT%6EB|N;vU8@mq zNI6iy`@zdouPajy-O{xxFjLNZ>Tty4Lo6U{nHE?W3?9N#)&-8KC4eX5e%eI}3D ztZmN7nbWc<`_)H@qepJGh5Pt_XjD#1!S}EyF1plxdd}w?G1i+6H>MKDvnX$WUUypI43b6$X?aHF|WTb*Y$*F^Zr5gEuzit4YW>nFhXuT+F0D4dYO?h zY2~QPI)zViE~dsG$Jq2ctd{q1wB*LtQX+AY$6>y#Oz(sibO&eCy5y|PD*nCw_lOZ_Y){U}@C1P^A$Ihf=< z_-t`;$J<41-rJWC94^~=My>D3dFdO?$cv{Rd$DV2xoeP5H*YsA6{}rlboJvlxvfeI zCb^~?x+))x_OJ28y4z2Gy1pbAJxA|cm}M8npk{fW`{vrNS7xu@=LWx6wJXW{j_Bz4 z>lSlG=E(B4-VjS`mM%-2rj=^=`FwtLQ2T@|qfr+Ym-sl^B?Y|lWHVGVL<}iQSKlj} zDQdH8h{k^w0&9vMJ4?`pSQgc`i+SPYCr|l1K zwG;8QZhd0VE?1-6UzMyG629n=;>DbUSGS2J=hhWI%9qOPjref$wN$@GWyu)Bkl^wY zF{qfUYj^Ft95N|%Tg(>CkSo?KFk}9x9;rDwgO0?#Uo31(>pbvuZVz$6^L>w_P6Qh+ zdLXgvrAgHQeA}NSOayUA0_v@RpTtQ|ij0swwk-EMNR4O?zd%azXWkEHXf!zMNbpb; zVTfC#BP0SDp}GIkG5!iP9a(q1j5(9B?4w)xOJ-$VT;_uBB_L{Dr$M9)5m@vsXunM=z=uwmN5s}9(DSem5 zb4+hKKKHDlhMf<(JCCTyS;c&P>g*G|Usk;>{p_N#it_Efa z-QkWK7BY`bUz=XH%YB#X$*udEA9Xb^sJ+v^uun$)LX+I6jFYpcpX+_7H9oNP^Ss@; z`S_Ug)!A1?dmc}muwaeHx?G=wsN0p`KI7s&Y4b(pfXQwa#8A*dsyQY9rSAMtnN<775Ce| zyTSZNmJUffpk8o`=tTiaX^qIh3Z+%I8f9u=6Q%BU-OP^=R#Ko>M_#dNI{# zkJ!<|Hp6`6(??M=rFRO2TBBFRcf0P0~cJIxUAbYJIg1>>D5|Vtd^xj*p=NeB%acY&J*+6XCEHRsW=d} z&RR+G@a9X*IJetx_4TAe)?{IJZlJsS+c=R@CzRXt&7UQU(^N4oBCbAH9(%8DfsN^w zx9@q8)?;HfppGf8aL_t4r=OYZb!B3*sY6xUNy46@U zAvtE$D3aI;*70PsG{va8?OtzmUN&7NYm1zImmsfi9<1BHGV0;`OWL^}+a6Smc0F)N z;lwn3|0Fs0FD2&VQ^Km~_KZfg+ZB1ixduqc|ACHXyP63$LF?H&)aaC zb%uNIKr7ZhZ!lJYglrWb)7FbJpHxCi?{L0iR`emgNTgYTxFh{t*5_lHAsg0`I59?U zc_deJCvE?PU~y$RYn{0qCB5e#w;ymv9QAj1tqIxKr4#%#op8K`>kz7M|3JC4Et%_^ z9(eDHo^kj5M_u-!qpB{4&)X7bl0E;r*1?3)qwjnshZ@gK?*05kWroki8)rUz}bj;T;I&)_3z3JDo^-E_&ByI0xdNT;Rj&Y%`_Ojupb6b|I zgKpB9`i?7UH$%1JG`cP}teoY0+G`4rYn*%3yfnIgORCC=oqAq0&ljc=R_`(EF5cR{ z^uqY%XMCPDe3=rvBR{9qe$@1dXCH=4MJ1H!W@s#)BX{U%N1*nEFD-?aMsH7L9yz>? zcR?~B)&8IsI&aLR{p(n3&YrOQbhCh@x4Z4Ed7*UA<2)sCnaAVUHdE4bKYTp75xcq2 zd`s*2qf(@kVF5{^S{}E?tjT$Nz4O+cWOhvdD^>3MTW_$p=8wB+Iz?_-eP`r)F1JZ) z`SV(z&i?J6Wv*{gonK#M-{3{r>9%4o`=Z(AeaHPyIlF#2n6+jNFW9%CFGfvrOeA~z zoMN$j#S@hW=gOr<9StTdE6}*IaNKI^ce}^x9P^NGugVfp3%|UtL9y3x!n7ljVKSC3 z)zV`Lnz8X-&K)1wC2EhHoHM6cpO8F*Xp+TR+}F$N?GD{Jt}w7c+qK#!C3Wk4b}EZk zpP=q$oP5_St>Y8+yxQUDh#k%G8&elvd_gF9GrgB{^r!WMgfzE&UI3UVrmpcD?Ij+`O zeeCk$kUAr;?eE*HpI;dqw+W>wVW8tIe`eMBESU$#_L#*k4myo%H`5q ztDak?`?@DpFH0M!oEN&%(bRX>xf2_`vhTb+Z?eozzBdNlY#t3CAsc6+Zx&VCvg@d5 zc&^Ibv$U=Ay98u~BQodPdM>tb1UF&swYB4udrt*n-rFy$Sx*utZL0b9C5k@^x!>Jw zK6#PaI@RX<$<5*gSJiZ)l4Mq^%wIbXaoISU8MX&4W@G1oTeZrO)6!89)ImEX&TZan z9l+H;Rj0H)+n;<-{B7g7g4rmsalVfuzNGG6;@jq67k;~&U~+B37+0Zj1; zx?1o8pR6XgKO--Go6T>t`3dLuzujyglkpn@|AxT7A@FYq{Evsgd?JHNVzIeo9uc9k z2n;rvMdXp`R34R%(5UdaeuP3`kq|14#%9wvG#-~rVNl3CI+I8zlNoFpm&BjY@gvv; ziHsk@E%-i683GLfB)U9g&Fk&#mWyV}-Y<*NYoD)C*2hFVK&grLQEHCpg>z~} zjp&UxOY)1heNo^}oU8ZL;|1C4!mK#rO0L9QyXms+C*!VRQ}pMBM3GxJJoS9fl51q0 z+j*gX{=mh#TQRMbYcJIMOj))Fq&;bHwxM%x z?W@kwx+^lJp=jInGn3NMqUiRBm+z*nWZijpe44z23{;X)c3i+)%^3m!eVr$X!)w?%Ot$ouO!|&mtivLy~LCi?2hWt(;;pF6`{N5 zy*fJiu);!ism8{)p?$ty-uQI{W|+Cv+PRxfyjHnR+Bz}g|no3mPZkFFYfZT z#0Qfp_}w|5)54Nnj}_g^61T74(vhKYnR9#ov#rynj^mgR!=6u0ElOrpzGFR046j@L z*1u@EVp8#!=tA{9ahE+*&X+MFMV@#OY2%f|Ld3UCKgyU{`e&KKZl=~pf7IdM5_w0C=r1F0(bM8!T&qRzeazj{aXtgek&||Xi5y(3 zx-dLJY18q^dzR`x_kCOE@K(ua`4V}J7oW_hyjnPL*iRAlUU$?-S*+_ut!cU0o@l>_ z)q$(4xMii2f@ZDBf0!p1hbn)1q3B83yJdkNM2^OJ`-@3j8IXT~-4u6z!?o8d0@x(% zk?d-8=+gTl-GQ=_t+Mw0f%{c2z3Ah3j&Zq8WF2YPZ?^H79LFhk;g#K{_kt>{sR0#l zY*ud9IC0GOgJZfuOtormzkzwuK;3xt3Wtm;;@Nb=8E520t6T<;Z@8ya|f#9Tr+BRrKUG@bcD;_=zWr=w$7=@=~p7JG3#{vgU#E+_a3vZ46gGz z`O&$s_kR?5bDk{@x_-UwnEFY^>$|G7Amf|oy1KS}5FP)j?#Qe6iSa4c>BsYz9ZU>6z;u-DUSoa6rI#(utKNH0&7aU|nDgao)8X#L z4_6Gln-X$#*Ni@+#zOwjcl>OE(H|o3ZFzIXpmBr;CbS{^`q|jJYI+0Cg(nv%>0slv??9U@FiD+qU zPPH_%qFY%b6odqe`uxZ{GR$0%7391qAPww^u>j!2RaM2~;LpMef5>|%2}T*f-$WZ6 z92~0f;~rM+^83-F3bHUDf0p6Dm;i?c;OQ^b`6UR5A&LJ-fIl~j^a& z``GYaotmw(nMCKbTue&*g)KSYPVS4e7l)-#hh!`Ib8gfm+p@JIZpNme@6awS=S|IL zOV6-LzJI*N%j2A-b52rCIqOkqapA-5S#^#N-JVpgwC22=RetwI*VZ13H>VT&(zGfr zr{2C?PF(oH`Qq}8s(VwB`l(j9^OFjzUNl;uIH!X3*wGiR(KR- zRtD2IBof+u?px;EB`L{E&U{A7-o@5Dw>CefXFhEfsqJd(RGDd}bCJk}Ed~0Vyj3e| z%PdIuv8~2;RTxbkpnV65cW(`{qxRWu^GiErIHB=Q6Qn5K?h)+%=-^A)`LorHJ5qRO zM5=FlOdB6uct1fRI^FT^#)i1!$^lGjT0%Sy4|*ov zOzdOab!--?e4u{qqrvvQ5qkod^*68c7A)mtta;~rxn?UOes|QuBMT(D!Mf8+Tn=8S z*c;Gh6u6V|DCXtOru?+BRed~5i5QiuS*G{P9HZi2(0sff$KCWD+(MkvD&DP)iWz&h z@XoHs;l&F^*^dv#l{iVhTDmhws#(9FVa`+edjE(~s~pSPV$PK}f3Em6+Igq$<9!>5 zHH+TAANw{TEn%Z)N#oKw%O_1&RO?-i(X;fjMXT>~9@FDj7cNOvo#f>1tno8L+c&D`PxQH$NUmC5h4HnpWe{kk?m3NwE41l%o+7j&oX*QqBW80gi zJovo+lWmT(Qv2i=DPvAMe|SYzwfit(>BWt9uI-;%kuqL^T()PaZwscSJ>w~o5_kV< zBBA%35%uE@ht8&>aVpaFON>59?91WsdRv)A5vZ;EW&B>A{Su^!h!%RYJax#PQq`*qLyMl(aiDh^b7zgFDz z_#Bd~XTp0mp(-nVKEAnI;ndqXoR$~yOGO-Qa%b#NDnpF>B~QLrnUp^`GlL$JFHyN1 zKdY(h!xAqa?Hyurjax*wn%o}OvU|4Yio6#YeK+I|P7<}ij~yI+Zl;__>w`E+Ui|bo zm(!=@DV!p0txa6@VCGZB%r;7gx!4Y4e@ThnODBcNq;qM zAW{(`kxZZx5%Tb>PKF;xupIG(`)oUc93lg2{bG`Mv%s)$ZYYNtIJAR=B-++_=&hL; z$&oJhFY}9IxTxk8qgy5#rr+I#ZpqFh&=9J~2w^@3^0CcUZ* z9#@v|B+p5bYnDA@U%8>rsfs@Jl5MIU?7;QAy>^z>8D}@mz@9#MB#r*wvwYpN-YXw6 zw?1?fyKb|7bWiT7^!D@iQ8&>&hd;>X7zR{D-bDu*2U>5ARlsr86kV>;)oG=B)`s0{ zxx|Px{ur{_{Rs=`8rGYro4y)w+h628J<3W`T~31Mr*hjmpl0&26t~(f^QfaLvrHqI{+?6K4GH(9k0+M|zPzGp->aHflXSJQfyzu^-OCTbHaX9QiPnW)UDs!(M{q#`1#x-`?n2xB9}OENEG@P`2N zG^{}gY#!ca4K@#Z*MP7wyTD>Fm~RaWi!tW)&FuG|b6*h|SzX-{U@ywAzwE4t`#AU9 zbIv{YoO93p)vx>gOaJ=CUwq_)&%XRyzx55D_tMm}m)5@Oqu==5AN&40-~P7M>**)n z|2g0LeN$UM_zlf>Uf%!I|NYkIrrvV#8{Ye$YTx{kkN?DDfBXYqvhPFnjhaUC`;O>PQ~8@6rwAmar;5 zC8NA@c}Ofy3L%Cbd`Jkj%>L}>Tue|cgFRS0*u^-PDCtoXY zzujx-+Y{nrLL3pIvL=LB7eZ_bAtE6}CWPn-A-07OJ3@#L2q9h)LVU5HisDOz5FZvo ze5nxP%Y+bLE`<0BA;eb-AwD96_^1%#?+PIrLWl(+#2JBpUam|kbJC3Z|D^hV4*4zL zfv?j-90J_$RR6zAh(j-ZZbekY%R>UkMk@PIY(Ksp#Mfbby;;5Ly z*CY6P6~3MjxNU(yqt5SFBEXz=>Bve=>O-$;^doz z_|A%WlUSU5JxKL+C3FJ5dq4;zm=TA?%b?jI@i@L-i?4@4Uk~Bypb$qN==N6IVUtMy zaUn!&quCu#gJdg6#*>(kbONya7iLlVyi*AAPO&(Njt&S>sfd>k;eADjp{x6ZIC`Wy zeD?CC^H**>ySQ+6gxY>oynOUi2#j z#M{*G0|G2k4+F@IWVQw}Yg=$OE@%s>L%Le3sCMPA*CJAN3|(!fue8?`jZ9xI(G$TZ+>L}3&yT~NPc zdcHV`8A9t7(8a@`3zn=Pg+ouqX?Df$1Q)m~`b04O#_YZ&$$J|F?_9$%lma&^~eaEpPeS!*6-ZPZL-V zgBz&T!$KTA0Ln)@+wG>`Y*$q~v(5nZZ!A}@R?q*I5Mov=PJ+=M`-m7iyze7KYWwzo zL>&6iE3dqA;3MMD_YrfvJXAUS5iwLbh@l?(2rUi+Dt0?{qvqOrTTSMiGnqAKGU>`=s}hu`_Uc#KqC*Mk%<%a z+RWss`n>J-@Kw{oL)5L?!U4C1gEJRvQzvXy%(WhCf7OGb} z4X*lNU)57~a=;q8YX9UMLRAnwu!YGvX*&f&4X!!l);u_Qu{JS*UB`C2+3Nb)Mssal z%YMBQL-y-c_7bhoi<5?7A)LfZVrV}AdFXapJLhNqH9ypg+QMX6Wh@4*IGeaV-r4kPYICMnqBkla@&6lHZu6ezFtLMDO4V3>-*2w1 zYvoVtEBGI)_5rL|2ay91D6GIe$RX6^8a3ieO-`^huy5U7Phk>(d)v~SOgUQ zo>9N?U!;D!i`(d7A)em9IQiM)<&O!mN?XAueYfcQpFSkS4?iTtk31yAk3J;Ck3A%y zk&2%dLVT7G;%8~dLVUIm;?3Bn3Jx^*H$n(0g!ly^#Lo*Meo+YVZ-o&5P6+W!LWqAa zg!pA4#Q!0L_&^Lhze6%9OZwMiNQwZ_Z6(RnE5aN?Uh_9;% z@%Ji1e0@cTzh4pJ8!AG4V?~HJ2_gQK5aOFELVTFuDx_hH@2ar&{M{8HzNaF@_f~}XpDIH95#p>6L;FctIfwe^L3bBX?@4@J!q>a;^^_2YK5CtwGdbE<|@9f z;p=nN;~V(nCcd7=*E9Hf55ArgV(66+zka47hQ!ZS#Lz46$Dawlw()fvQ0(B>2k?dD z65#wHfq)jotRSET*|3J7*bIp;!q?x%*Wba{hlCjV0?RiK2{H5lseniD_SIBjtg=0U>J3K8A*;B6x+Api?;8J_~qdX;ig!Cg%H;ch@-Hj zn4DeD>|dN@9%6oC-eNxc3|Ia2auv<=r;)4nm2=hpzu{a(!i!joxXR@YVi$*fh@FVB zh{cH6i0z00!H*Bby{y~IqQBXTRpoEeVzs}Nt!N?m8_roJ>(zs6akA|vEilY$&c>Zi z5M?r6li5ZflU_TxuSKlS3IRiAGBcjUy)2B@>3^*TzeE?j3jyUpJPBo6=~u6Toga%f zHpz!7LcBy;!;y*@IlMS2UwIj^s-JtXB1RrwoP6smFAoWcFXDVC&CqiFRx3%h#pWHn ze}960v*G0chr+%Boq9hU3;Rh8s;CIref&SFgRZ#Kcer&AAEvrLh`K*W zdt9n}_%OT{hYlY;Jh<-nJofm5==VoZ_eW57Kk9zZV~-z1-S2tq@dK*gzc7PMn;Su^ z*A5b35$4*zuLcV<*AJ`TPY5BtQT;}E@5j||7!JNy{l<<$|Nis+XonFpRuPB(+kz0| z6>&(sYI9?vA`ZPYHzX!2;?VXVY=s@@N`Uq8_X~084>l|CA}I?HpnUZizq#4#%JW-6 zvLl}fg3Ve*96dgs?xb1J8Bd!@*v;hgGU-Ki@6< z8I-&UsD}oOx0i!aT?(>ZSMud&@_e)vCUHbGzZNHwp-2JQnNr9^Cvb~cXI!u5Fq zIrrj1FKQ~FU!z_u1sV5wKHB=me!xlFHn2ZY4!g&=JLm7nvl~HkQ(lM@$taRbgg=5@ z&aJoORlhCQgX~h2W;eU7d0BP-05V^%0p>D(yUh)Kd;n~iX8DI-O4CgCzR^z!#z_q$ z!woPE2=lU9_7qURrsT!<_CxHDL9HCjJ(Iy)IT%$R9tXCoP-;qNQ1u#Lp>OoN2 zc-HBzrQ=P%n|A!D*7cj4{(6wYcC?y=t@WTACs_(149mc`sXky7`I!2R9s0Mb->?pR zv-%B-1SCB^e|I11E>6O}@rV$#;=uayS|KX07oze8A>ci%pk3^e(I%`9FwesRfh>k- z8=fQVq+xBqxJdZZo)G@AA>I>WJ9zjt*cg)c3}WxIupgG>SoTm3US;?jhOkx)y#z1y z+elh}?9&9~y#V({0QaWdfIIYRA=roYt$z*hy-E8pb_H>t2JxFeO&}g(HzhC9dzfPh zG`?{+7>7QgR^-J=l>IE2)0;t(jW-kHfPy^DqmBq;i#mn%>4n1~Ah(o_iraN)y zOMm_Q!-s@8^z+fzh7T)i1IUbAX8R8aadcuM%er&pXnAU^6|RTqXRH}_#`P7Syx`z| zvWt^r&7}Q+5Oq=cs_%dMpFH!QKln=@ANrhcKlVF6@y>r0{OP;?-4C5y{!#f|H@^HI zk1u`ApZ>sy56pi1=#6Lo`A`1N7u@`0_JPki{@aiKv*h!C_}3p^`->NTclce)XJ7b( z@JGMvKYZsmAG^35f6>S{{F_VP@z($O%`2bt#G5|x3y05q$E~kFaN`DI&cKpLaul>O2;*Az1GQ3_BgI!oD+t}VgPJn_N*pAd_aZz0+DIwiW4xT+i$ zFC%D$#MDDVR3PRK3UTN?`ykT9(0&MBc3!>;(g&6+5>*KDAr*-z=nZ)MS;)QmM*RA0 ze7#u}IErRG3b-K=PRGGsE5y-<+ku}3HCB*@5CIeQn&+N8dyVKFD@D-pL!xnfwEqzQ z!*zypVo&W81{#*5`_Ry9nnBd9ZM3&LweCi;T5C18-hT+s$?unj@w>uiJMOhW+WUn# z`sT%OGl{RlJa^&p!u9jDOV?@(trj3BWZ$*%eQx7#dqDem`SYnZj`h$$KD_@=EZBm5N}mek z2i(T12Y>L>+W5hI;~)G~8-KGqp%1u?zx{!~_v3EspDNBDbQ>RiebvVo1072jD80 z!?s%-Lc9_dD|j!CD5nA>Q44`ak3(sC97mcNRL%{4{y{a^BF(PF2o61ah_gUyRi{O=i4bB9yvU>7AJw<+)&WT zFlr3nl7+3+S{SwD_C}Bd5-`8$=`AYlX0h3RyC+vhWGikwZ$`u0mZ$x;EVehk9%Ona zN#i$lg4@ENi$d>5UDu9o-~Uv6U3SVqy`BS ziJ{;H&HHdwQ^1(4>f$3bX3*Wb-1d_wjMk;M9Mwuc%h9p|K{lwLrKGtWJ$u&=ks5jk zqqP{#FPr{lLmoGO93N1Sz;7_n_>E$Dke|;ZpU8&M*C@;(QatjQedWnip`@o0L*jW zchLDUi4TI@8^Z)DP4SrY#*(zTT(5he%ehu8t&mtFcJD7uMUN>So&paa8%M*^Z?$-m zs#FyX5*N*7ahfI4a1-$^)d0J2VcCqMEQqqSp*U5up2K_8SJe@ns_y)e!*_vFNt!z{ zj%q=Y#EFuH>yrKghn&BD{pxked{RdKca9uBmg{?9m&G||f-24)%_!lgpK|6UnB!QU z#ULW%1j1QaeQ7eyT=rKOR~1S{-vF*$DQR_Y0~*jEv4CdKoWx_v#tVZIZuAFnsIhZ3v#oC@wn%qUE3&S1t7v&s1+fqdY8#!IBDfyUGvjarb)AgP`aXE%MU_ITAbPY0D6Gx0~R9e7MNK92HB$^qsqfoTit3t zT$h9;(b`~G0XrFJHZ;_&AW6eGT9MwchXEP|Pc?9M!;hk%4e8Cgv27Uj z?DK0_InVaeEbeeKkmk-qrE*HCb!@BwQY{A63C6B{=_i>1TvkzdMe3!aI!Wt*DSbX_ zIZaLFo4V5L@XM&zk=5z^%j-ebOE8EdXf0fm!?)(zK_shJdYu*7kagCSX)I{St9y5- zsKP~%0?KaK++-Mst8{ST3Dh5vs;#9gSy`Ev#V!DKu@8nP*Cd)k<9?E@+>t>$4X|1% z`lXTc^i~NNv`Tc!BwA>XiqxG#ca9vMO9%(DYH&d#w40MWA;?=*cT(?8RMH#qyQdYs)0|`8kL4#m?go)FD@s)&(3NsfU0S>*&&IuW zOGYu);Vki+*p89=EojNBOA-O*QP7raN!-yaCethlqxCuYoF4ksbRlXf277Kyt#nui zpp!`Mh<=aCCiyDc@p`I?K>;xgkfTF|K(}!@OyhcD!q8+%A>t|9X0siqfo4Ib9B+g~ zgi}ThQ?r1kFRBX^qo}4YRTxk2kSzT3N3|^cY%L4x6E(H6U5dg?`O{q4_#MCbVUmqs z{l|ZcWFw3akd2jc+4$Ph1|ciAA3dfPQHicXv+F;?h5)rQH~!}9K_}h{WR~=T`ND!M zpNGFaw<4d9R0XBGDfM^)>hat$)%NuO%Ov-p8YcOxUN3Z514^-CdT>;vbK~PloQ{#r zb}Z@TYzVDj?dophlq#AXZTnGwv=IKADjvFJIkbT{hpG2I6V zg{Oj@r~P&>SjyrAdN?ZTt=K~6X18_r`sE8e)cnhwse@}l7TCuGBnxPF&5#Z0VM;vt z!V4_rSL3)%%ZY4IM@oQeBAmQ4Zz*z$B%PGU#^Lq}*TSZs1;#;vA9A%9wzDv*Wl1m1 zYAMFmASFi+z}0)asxq71Oxo0BIu6HC?eor$b%Ty4TWQ9siI?EZR3>24%`8Z9HaU{0`nFMHr;*p$Qq#w1Eog~cU>JIjh z>p?=6lQFsIZw4~$C4mfX`^~JqBeRV#m2nj0+8FlK7`+i0rZU}#x1%vNySX6&ojep> zLEduhRXCm*M{2YvB0ulEr)L< z$(fT=6ZQIurteQr`4f{9{^VrqR4{w8USFGDTb*sLotl|kt55nT>!*BwrZsco#0i7u zoF&EO6zp5vzjY0*@X&rHC6!ry`mJ-}y2rS~C;u7|5onV4?#}C_3pcLSRw**bD|vlp zvwI$XoSGlCYQ1htgGHN4w3FXh(mchGB#lzbp0*xn^Ny@KT&inu985~=uKBRKL|P|3 zQ@^hS+j2$Q7Zo3rm^qb!F?A#rK5Q*f(H1bAsd8guw3bqt{^2Do$aADeWT|Q!iYuvW zO&V&a%6O`3p{S7pyR5Sx8us#Zft`;5y>I84QzO%pVqb@N99WGwAb=8pLbvC zQ!-y>GUl?lnY7pBEwU)+Uih_K=|eVXpnseyf-JY9-7QXw_PKg7AX(4LjaqDOcJa3} zfqGfE*=;FQNn$F*5u zDB))2RN~r_w|QpPQ?4aJA20U{iyIefXX32<#g$mCa$y{4F@TRIgL~z@9zqL0!+Fi1 zLBxBnoL44&2Z@-44r_Oc(+d)Ywg)w5X@~KpwjE|0aWAVillG@a1`(l+Se)(saAcwEZd$4GKGHI(o;rp(f&(em1|jF|gOX^y*$5&NR|-eX6T zvPTsj39fNKXL|FsQGYtnACnrnx z0|4ut%0kcb)OE+v9JsshVR8aFwHneJlg;0>)5H1 zxg4wPe3h2W`D!1^b!(n#QUiuTj*N`V!+P_a^uJA2Q&%u$G$_y2=vWVntd>l>eltL&g;q=Y zvJ*Cwc{2T#Tq{ix@+=a%^N#_z zg}yvK-U`!A(h#zpZqT4O5=q~+j(@wBh93wTll4WJw&Sdk_?_d%Xx|DG=?#b>ha$*^ zPz+nqog}AcxF+>DN69={*JLjRMvnKo>xthAY6wt2u9l-ChsVPx3z9Xz z8H{g-YoQKbr!A%mVP}I#6#(isxRVBYKv)NwtabcoyyHjydXU^x?PGdrN&QYxQ_c?d zPw+Otnr*cyTSG=WD3a%FlTelAEk|h}3F&D%@>V$bK%NWW+mms-C0mNEX=d5Ol;45U zR4QapdoOw_${)&xni#Btz%$vC4UcJvPL54XjmlOM;sKq(iQBCpk=tPsw1YGyJI{&w z#V0=?&4i@VPl#;0@U*D2YH85*6F&>2r>nx$L`MzAOJmKkRc$`8x}P}PH}TK2=yv8p=-PIWS-NOmrF;#Sb0 zi6&36`oPa@Y~-5f@)V#^Hf}o|*MQXQvsw;_v8cQ0xgA*>E@ajo8?d`{S20#tIZxgm z4YOWfVEG-BS0m}m>H732Turdw`WdZ08h;&sM>(OwG$RyZZA!aAGh7RUR*s~PdQi;? zUu>-*P2`P_Yfa=4t%)owA~RX9>#81aTV`K0f;;JmovU&j;saW}E+Q)N2UUlf@q@3) z@1}Bm&5Grm)D`fOm2Iu7&gsADTp_KAdKOW8r<+OEuTk}E+}%mS^^HspH%H`Ty*^W$ ztWTccZJgvl_jhU6$!T`;pq>&csS!A%TChUy%;t);f~~L_)IfuyOpn|S7XJ`d6{TnU zQ7fHOuW-PShf0sM69aDM-S(sI&Vn{}E991xI(G9|e)CC13c;$!jCG7nQjFZY_>+zm z?TbZ=1ofm0pWGrnxo^WnwGTLB9;Jrw#Y9RQO~N=_ap_F(WO@+|Bi;YCrX9$<5FX2Z4k;<1g^a3-!mG)8A+1Llp5FjY*s z=9^IDoOg6jWOd{)M=iLD&~Be&ZPB!KHb^p@#E&DwhjA#m z)lkO7f@!am^~tHmxs-8?$xn+X34+*Ze@PvRf<$nvc$jUdTPcO=uu+`k$I;>8;VJ;r z6>F!xysOfWnj3MFdLzn3nr1=mhb5FriKHz>_m#?< zd!c;@8fSl2AW?^-;6Vtp)RkP$9OzXIQb7ftfLhP&oV}uWpE$4ZiXUFE>_}z7LNr2z z*LyHSE$Kui4reI-q8hd&<5`-_Ck8~tNmrxuTS#W(NIAc&(xmw)WV{=R)T?AY2^ebNvlLDID040sFoo(!*6CsWIOVNV+A1I0vS3 z0?nmnv2?0P0|VDn;Ax&>>6y#IF)x>u9LzsA3N1qb*;+4Z;tyBW#PWHHcP=hA z_aZllG;B;_$*2b;xxolj{Il8^*pNfl{!&s-Z*iyr-dm7)W-(otdqDw*>l)?82^-dt zQKXZM$*O5~OvU?ZrBX%zngW_boOzi+7^whD+QTY zlqx`Rer&R^>p`B?m_VlLX)ze~uIdCKU}awEwllc~v`8PQk}P}A^5AIsScc+M#=>qP zI7qDAaEHkTB{fcNW;f1r8};su-=^w_n=GsuJcl_CyK7Gw!!fi=$F~sr8U->y$}du_ zM~UmAcw1gN-jP|D1g){LG5Vt&_*-GLJ|;&-mZKYV3V1tgx8*8AJyrbrYS50iM|qCJ zR7P>q@!Ml6zzl}LdF7*=HI~8GIhH|I7d;k2Sq@hqvvscF=r_OP82n>eRu?O=v6xNZO@%=;1OYZ& zwe4Kp3X&vj;pmnjOWIG3^n-(g7wG3|wt?_WUhm{E{IR2wlD3SJ@PyMZk!i1s=8Gp%!cHczqqIBcV=^Gc0Ye_#5TkcwmiA z(20{B_L3?~pLX!yWIu22NP_ajm3vztS9K%j==KxonVU!O(!QoB<%>ZSB!2rwtj;kQ zi@i5*4;#28&o-GnF+F8E9vnvFkrVh>%Yt^Wp7h_2 z$W7JKZ-S9KCRGX;R zr%p^wOx0)WC#En6Z+d2Wx;`~MJ%f73_2WYSJ69g`OUMJoMvJKjc9RF^D1>?uiQ8g_c^%#VV&m$rAt`f<*PN^hv% zNh@imAJBF$=le5z&XHHH{6E@2G zSHtjz{dRkVkXFPhpma;Uun~8H7vi2ZDF86=@}ghF~$ax0I@Zn19;)*eMgZuM%^3}j6M9pf)Qm0q0E-0W~P1CQH2gTGJ? zhmmnck$Z|&>Lp$%7g5A^F)yp`oB5G3NdabY%4IAF;hOZf{IE^5g8f)C3H&Tb73c`b zK!C%zzm^4vu^}txaJU}DNs!9t*5afYFfyJa4$prO5|k?gE(cZNf4{x$@1&|j-QOrw z)rf>Z+{;vl9M`09Bx~i(mNqBjh;?6}%ueySU<;vxm!f97*9tCO(`2mqwlKYfT{|J} zs^cJ_yb+u#$60gfT?^7pKbax9O{8?;#x>QGeA-V!OhIa4WEigdQ7i78qZBuFXEEfr z_DsB&u2CvNzG%#z@#DkvIX25x#d(qHrB)DSVTLt3j{$C<4#v|7vawFoYmPBh2V_Ml z)>sOn)|oK!6QkMXTg3bGoO_}mT^KC9xB73mKDbng^2eJy$vba^KuArt2#qAa!kUa? z-pcf&x^tP*Hz~LH4lVy|nbCd@9)K2Q%HkW4C+9emwwSlo(h=^HvcmszfhaR=dN{Yl|EN zIG{5WS@fgaXb`t{uGbm_AH8x%PZ)+oHTv!Kyv3-oWw91-1xefA@#M-VT*dd*=8N8YOB-EY9&3${QCKBq zd()ABN+&4GsMZgzIu>{1B6sn$pQHrr-3MBz$<8~Ij15Ot3aM3i@Ot;A@Q272wb3#0 zeA)x3vE>>b2iPqsIEHb~Giv5H?;lmYQf@SbC%9SI7b@5MupPAK*iU{wAuFan1H#Ej zY}T<>utn=|Lsr#K&{zIEZ7bNi&Y4S8G4&TpmQ2@fI3IAJM_F2~-@HOcd+dRpe)NNy zcSXJ;ca44ZXAb!|^~fkB9Q6S_0I%C&E8CDAKiLctx$HSWm*bp{-O$ObV=@ib5r?)N zknF*3a7URx?7GZ$DZPMiZ(ym_Aq+5=@%y9t>@Ez)%H}&$uXj>yBz&A(%v;!g_qTOO z;p2UVL(sfyHr)3wzlO|)lZ#(PWf`Z;^(IYXJv@ zi=t@dJuwzT!wY*16P%ntV%HjR@v5vY;m!vXCtgzKnzisY&RNqVxKFF<0cMmt)ZV*ehO5@X+xH*`U-WDu$pVkS z&^9PU&33{iI6}=lC7IC&uy^@_$M6=}@l)xFQVt?uP$P|L8I+N?+G1*y);FDSML(5w zIdKZbZG~2_btd)`4ua8V8}hlIR`H$=H@H1%F>UHN)J&jZH(RK1wwEj<%?(>8mt)F} z>MrZeE580GmyYVe|R06hk;Q^Y8m#*cv(D z&-B7}3$yC357)24d!u2{a9`V8M>>Yg&w4KQo4q6nBIVGr#B6)vWg{2WkQ-TUB5bv* z?N%R3OAm8v_#9J;GyID|#xMGCeLija-QYr;To2aI-*&2C;a()HL^`P7Kn;321tHoYB3%hL>((@tQM_1imFOYTMa!5zrbQ@+wlXdj8 z04j32xR?YWcU{`1UvVBTF1*M6>k^{MbcH8-9Y4Yn2YVGaZC_qWFZ9~&owIQi1x=j1 zc3+*lvUHu&pobCS5_E%?Qj!`w5oN?yOkf|L_2JkrEq^^ogX~I{=U#C8fSxGZ>mc~> zvILOD&2yoP^6Q=A-8y7d0c&dn&qkP6iPG)~$3S+KMd zWxmTs1y8Wkp;dn%FV+Kh4EEh(xXy7zPE94nZp3+-zpjqk>O+A}jSI**df89b12Wna z-@x3lupUI&Qsz>DW4IzQ2wrfiIgp7vd6?8ECh z!Xt55Osbh*CT&m;TTR217FguURJqWgHrY5TXHB*bi;9YUQ&;g;$k?ak$D=Yo|RmCe=kLkg6M1Ss8G2Q#f*^Q%*Ucv1V{> zb6tA9NQIxkFf#xTBpzV1hdo*$1o31X=~kQ~@`fSLY1X4IhRs$WKWXEf>t-!Zkj#uc zT{_QA*GF`NIYfcvS-AP4mwF?V^<3^{QcJP5>;R@n+(4>^Lo{k0q7<^5=_A@Rz zHJ@tLcUAPh2yHD*bEV|)^LI?3B$I#fy_W{GYUa zvg!_K@Xm-TS4y$N`C%YmTd<{eFy4r~bxW!{1xy5eft=Ta%#$lCca*##^ID(0$(a;M zbM;2F4B|vdcY))1fR&e^-n=ZxRI-Rbtle{yYSs4UT`6SFcI&(g-pKv;phT1H$cTq> zOToQkhbK+-u>nHs4YV~x_jb2z3{||W zI&ZK+BR?Fi(axg-C zm41NvGr*EPz_Ak)UlmLR#n*~$FKqW==lZIO$K!W>ow6sTubQ&f<)5=jK=sx4O0mVD z*N!nE2Si?fbq1C{f?#R^*~q z2kd{5Jl_^|<&Q24yR-|39Ion$>ZERq4hv}|iz?&?tj3nFsnm&GsudEZ>qOsq@rh*r zHZMCc1b|ily5oGJ_dyLwN(pYz$ydgpMd(A?Or5hu*X0x)A@$BadEJ8pefLtgPn}Q- z6HykL=7pcPf+RYaIPePn(_oypWs5MUkst%OU4e`Is}ZBEf|v_R8AYAePJ6I~Yc1O? zZLNZRRT5<`)Klp6k+&K4)lA8tSmXS0PIX?aNyZpS(N|g7@M>#e(%JSCLwIJfr}{>k z^wrn7nM&%j=F92@IRP3blMN}9`8UX@n)E<&DrTgJ}hfC6@^bOCf? zXu;OkjH_j(DPmiw=FP!5X!Ug56?e>?jKTg>R(7*OD5l?X`E@ zmF71oE$m%7Kg%WEzTL_tT}$ab=_f5L8FNL9xOjxjAh9?{TYr~r%F$V@jFrRG)$U}< zw{W*^iQh1PW|>AcGXdpOhr*Wm`ezL{$&3|BVR9Kodu`uk;l4ilNCP<=< zR)o&7vP*kAehTVEwyjZOf^=q*0q7J%s#)QGeX)`{GqMQkf%8Z3Z6#o<@WQtlp%8dr_ML zQSnyUFdXxsrkG*8ubuX~KH@=$@*C0%TP~gK+I}t-(pcDPl(e{_HetN4)CC|BIhR>G zUJs!kQAnz?kYX2rc)r4BL2AOsR9Y9Sok<<4U|h27eN_n(-28ggTp7M#3W%~Bk9+}b z{ZzzqDMD_Zs>;5@1aui|vK+3e-awK{*4`w=r6v&4?WLIE0vFOUw{xWo3F@{+EL41b zWB)oqD@`6i_`_uNsbI&T@(E;e(`uzvaTozbqGzb|EIdK8puKT~=7Qm*Fy=H%awEQ% zq4XoW9bmn~WNAceP_*&U%&ERdUmbS zb7My^TE1oUOJS%m1@+4Ct#R%A%#pz{Aqm8|GkTDNvaePc3J$jTP zwsmkUCptm81!UtmdelkPLD54`W?7e_W;CBEd9mm>Nm!IG@J@`7QH=9)I9>Fcbf~bs zv(V~BSmxR6>x02<2Sd0s1+wE-5$U}7h0hh)QzkHeoz?J$NY*( zCX04^NBRz29veWd5#MxCHdN_dys^YbDz8s_CPOItBU@dbzN`Uoo0F)p2~Y=DA#THD zcXzYs@c|$0OB|nXRQ5qHUU-x7Tvg@Z-!H=?tpjQZ7~7vU~2!OoC!cuNQHL3OOHzp`{W76>@ zak9mATonxGuy;q1qQho`rZL$8Ur>q;z%+5N7G~M4bd4;qBs8^Ji#R{9x3)T0z~fV> zW0p1BRb5WZXyq`kHkmS7bE3u^<5EE#!p4DjMn#QCExdGRsiQIJ?V)x8syUC-Io>5U?=qZ}~68_$dyz%acXlir-745hn~CEU~;)~(m%q{?Pa@S8@|53|=Z zv#r3cTlnC;aCgBv#u51FZ?C^02Npd*Rc(bgjH>lKMRAcFIXNLfMS5DwlzA_2KT|V- zjJo>%`CEt#h6@FeUQ~LLuB$g1^ZBU7bVV-{o(|Yo_9|N-1c6m;&^g2#R zDxnR{cy*6Q%$4cFdmX<52!{~@oMca+{)kj-MNf-6`a_(#s}Kt5AJ2hjf%-w&UP@B9B&_iy#5jZ!A){ zTjUD@U3p>VO(}UcSznIB?PGo9F!x$BIX~oy;>>}r1Sn4hSOwf8?y1K7u&8S@dLthd zyyeGCA*I8nY96 z(b269d&?7NZjnEeTB@C{PC$lq=n?%yfqI8xE?n}y9Iul(PGeLOdZhObrQ4rI_5?^Z zwz{bqW%Y!IY*6*09QNKj%o#&oAT8ttT6teUhMbY*s+YgMf$(K2H>5{ZwAmL)Q?CKIsnI0m+VkKc))rb^`kkE-kGiJ<#>Ib1-^mVQ!kag$PWm1 z7#`DTg}l!I7V5x&!z z-qG*ElB$vxF1eDW2SAmYqd;-FxT>Bx2U0Y{0^`=x;YMl7wIm2?8?9E2E^m}8@*VQj z)TvV^>ZkIK)ZK1lX(sKOzO>62S?;YmU9UoQJx)iTv&mT%)sPvETH!(-b?X(~xQEP( z7>`_Q`{@Q>M=4iv6M$>Z^+Mc4z^S_fx2e6i zS;5%EG63!?u}g02;Z_jo_O0#T8g*PT1nSZk-RwFij#l>RxF2WFx8rCkeBlM_V1}v5 z1-$Qu9(}n^`Q125=_*j*U2n#*46Sd)F+6Xvtb*p0-OQcXLU+!^7|4)fFW|{{)5zb6 zVF`d_CsC~fI zQ*(&?t68pyFFP{S?KJN*ASQrHFA z4teE?&bq@LhBy3qPuho45;&ZdV=0i4Jf|!aUvj$gToDHj=cu-|G*j9KyvfxfuTbIS zxUEyFxLnt11Z=r{J^;2rmk9`sAUeDnwPaX!ZP^}$gQ8gyZmi_tR6Om*$gz$r7xY(t z4abS!ZooSLb&P^nbJvA(cM~v~jW+_n6(qH_Fle_L!_Pxs>%%8jg%x?n@d)bdV|JAN5g=uqy>Ru+w#IS$jv+U0x=kW0TeR`flESKZ_|O`K&tDmxNt=+`Vs(6-(#~hWxW_aM7a1%2axZ$@xC;U~n3+!LTuze`Lb{d%Q8*jiuZnv8=or6 zp8`qqr^I7wFyBw~?qZkQd3@?*?;W=)e>p{H)eQWX(^Oa{Qkqk~j@=?9chg~>-}5I{ z%Wy=3a!<;~E~-&c1I|G{=rWrZhrRdG@^5B$OnT4Ws@G;$o`5|>?Pdl}hqJQnMdWzL zWt!nKm|kSmYC9YK+{xOb&X9`ERN$c_>f8+i64u>)NJa;cIju%7%|*#Y)K7go*jI>Q z0QaDOn8pkG$D*GhWt|CTGlmas)X-~XPBq9c{>qL5?7-MC05`)9^o=U_8z=dTHqBGI z#E$c9bRraZmKjhv6+n^Bi6Ywz2JI zUzl>FNFBsUf-t9aJ5l604k$fC28vX-Rh9=s^(Tw6igHnp&vnOR;}Z+1%4#~eYRMKr zTd#Ai_GzTKw<^V&?Z$?-<;vxSfx=$@CNoz@>rVQdK<;HR!56Z4StthO@vr> zmr9Q7wY)D$SBo*9b2(W6aQfXFbo*T_1XX)W^VF>w18E?p)WA_UbJk zgvFscEXE3-#S_ykq7Cg-3(TE!WuTO?#+ZU`CZAj=lmY`mEd#cM8$ok3?RC;I=;Ne8 z73GK84l2~SQ>(m2*u#(npfyo9$Xl^qqSIj^`p&e$wi6V^-DeQ9t-$UMkWF3f5AtD$ zci%HRn}>VfKJO*w$|#bqu0M!j&nF2i(&~!J5fj!&mK|xM)Gbq5Dp99N9IG)?`itIs z^Q7)3T{on`Eh-~ro{vezP(3o~6>4$HJ6Y`)z2@Rgw(uzibF^zkZ%dTb<4S-eD~e*Z z?rUySE}p#6*HtAFR^p9g3K9_YPX0A-JQaQ`qLmp z$--QJ-MAe#cld0a83toQy>gAP_zaNa*U(THq_P#Rtp$9Irb=tiHq6pd9;ZCNxCPr> zFl~z4LArR!Z4m7yRn3UWE>ajQroVRD<4cY7`N6>>bA-Sp+=B!mu!q5n;-)7ADN}xB zy;ku@ZLy7K1s?^qo);rK)V+zWyO+m@k0M817-n-Vb84salS{-jVkK05G1O%hZV>NV z>m_^$xFPHCRI1%Xp=2*<*HXIoktkG^b)*!1Zppc39BpCalO=wX;+mUAr!@mDcq34! zh}zJqUCLm2K<#1$He)N!l}m@tY!NEbUWW|rdzdla_XO#vB+|gusE$pa(9K4z+`Kt6 zm!HCNd^u_j4XkiOJoUl`hH?cV#q}WVwc(z*H!Eq5XFsjFh0%(%aAOErAt4zuL)o|S}!X$J;au#?l14xC4%wYzQ(WC3NcBo^AEjCW5oSb*6) z0M!UiPMTr0gJH`XXBm~#_36I#wDi0RK8Ce43QOc9uvpNXc9WDjs}EhJhEcbAozBh} z&OXMtLP})>pd=*kEJ(wG+NCU)3Ni;Ddmofpymnpm{z_LaGLf`#ZcqbPwj1Qn03Kgx zwGc$J5ojjw_)!nXsop7txtqzhQQ7ChfHx#D>0@+w52xngUsRDjk9X z=bT2%OBLD0PN;(d<~-I+2aj59W}pJo9ley>dEE(3!DkRMn4F4})(t5MfZlo_RDW6} zV7Lq0+i~QW{&E~|rm`Jw29C|bsNArLI4ck@K+0>kg(UBCSO+Gg8^Nj{A&v3zs``C= zL~3o>`VDp)b8fWcZVn>H{4_uTHX1OSLU1(#GyquSTyh!qmM5q5E>v;UoGh#udG2sq zEai_uEP~^7X@Fa7z`oWP#E2cpCd5z*G*nay!D`&v8P#Yf8$80uvA&n1cMw(4IvBLm zppjczb7RiKW;VYxdN5Eyqh;c7iXCmB2$QLcKB&U9>&-p&=DZa?7H<3$b`n?YO?Lp@ zd@Ln99C`jW?$3l@UD>N)Xy2Pc6{cm=V#Y*7pBG^CA@j}vbbUH;V5FS-lnx)6!}Z9A z!KZ@&8w17f9XA_3t^*Dt>0<%QbMYW@8nA4rnZ1Y3cN3fRDV3e{an?h5#~kG(9m)t9 zZQFc*FHC~g^{Y#R0=@$fvZc>tB=*O zl_L+^;4PgciJWXFDMT{7jKJ9#z#_eGAo*Be{^TGVlisM@-UuP#QVPB71esjj!9DRX zd!?D*W|eVlfRrkoJTq^F**UieB$XKJ?mjn;C0b99VJX$iVwmE_`*Vvq8?!ZCUI_fG zmjq6d4LytJ77H5-tzDUfT-G{XJ6%-`!H(CE9&X!E@sH)D2JYZV_Bc>i&F@i!P7$=0 z^qj4O#jg{=U~9X_(KMg9?EI;cm%5?8RYqROHy<{G8eM(9#$!lXm|2gz87CiS7`a#C z(u306nD>6U>H=nn*lw^wn8OC&b;DW_-`>1;Da$Dfj@}oem=WQK3;CgjITyLzzw#C} zzam)f?^lTiFCU;O-C<$t2VXrqtx7vmi&NpHU1W2X2j%W6CV*qD+wtofh0s;&oqfQH z-UnEQC%3)3ac0|1Lwbel0BO6BgGx8%D#UI*WJKFrEk4?0Iz&ZWH2gv*ZjFqOz&_y4nIX2>0P;=ph`nvbK!)n-#EOoeoxQMJlUeeRr zV(9ouUGZQ+%ZUc8!+G54OI}(*GYR|@cP}P!CodHTLNO*iM0gVPeURpk@Qm3slhTi5 z+-?Pl?ps@O6!9>X^fjm4!|y18#vQm0WU%#-43ls1A_DFU6LD|yq7tl)akb0w`dPjx zjb6D+RjxqUa-~Z5N%msJejcE{3ioN#L;7G>gR=m1&O2JyFc$2MurlsO1%wqyY8LsJ z$D|iIHbgZY&{}z?b}y}^bl;k@1|79&1(=0$xU{onW}_6NPRx>ausaN(NQCl&A)v{& zsuN1)O|M4hQdhYdr#;#bqDA z3sA@3kx>w|a5XaraD{P%ZgNduYh!VexPc#hGueUWpgLOEo+nY-AWd}t-uTNA zd)!e@=Bd7SlX&+rrovp(2T3u?F7}jOx0h~o!^o3#Njvt=yPtuiOJ0&V)X~MUvM}-3~1im{{GQpNisC(15&MxD(XItqE% z!)de{U1T~Z7sJgY&ce-cnkjv)LhZD?oi_kIHwi#xf?oarSZ!!)=_- zjgR{s_8_mh{HwWycSr@u}&F+3~3$n3z3zsy;&eX3qeU&0ebuYS^6YkqpQ- zi4gOx;#O7gnxADs5;@j_T(CCu3C@ykOwrtQRaeycJwwF201A!ETbyFpQ9M+a%GXdx zOIc{2?ju++Yg9p7F@>qEK3GhyQ4I@~)9VZ50uRC%-T6;zZs)%h45XxKQ#-%WfZc&L zuN^dW%!+x9=oDfL4Z$rCnw_)a<YKwV5-;3#GBx- z`g)s-7jIlUuToxeFW2I2sd6a;XVhuV>Pk;0>XU_BKW9SFQ!d*+7j01C5$T1V&F4x} zs}T1NNd@zS#P4YK+~uVX#aT~_8igC_M=)au!&Q90T{W#`8QC;=HplrDdcPKLyIV9R z5N*n4_R*-np<}D&j6dy0r#nGeose1N?Q)`CNAqa5q~xR=u2O|@6m&`ua5p;LNqHJL ztLG6yl_s&?C_u(!^-LJqZIC89Q_vf8gpgj=)L;kzjYsNpg*bt<2YR_8YsCU4p|RDe zpjzkQQ6r|A%L#jXAf;4n*-cD=><1qUA!6v`!dgCSfFf(0Y(XD9mrMfARQ8D)^1yw{ zdGN8iBefP8v8}Y!hCvdOx@$tc8Z64|`L|JYI^i8Yx)zT|RWrCS%@8uE_nMZ}ZhOox z1f*B~r10-HW5CpP8uCOV|)2a5DdyAPcSI1 zR`MCEBryuY(n&AGUs^8HYt5dTFL~3Du&m_iRTG|L7pi;yc9`*HZUwQ47gwKhD6$|o zDHDOx7xEO#_~b^N`o#=!Mb$ykZT?&q5w8LTafyCA)t7Lyl(TywWrQZUK*zRyB3zba z^tLW>A4x-cbXM0{Z9ILKiYHZM5q!SbjdP?t)u!0b;C7e=Duj?aF06%x{*Ml0a}p== zMd`hF_ysr(USOXVr%xN!+chdRLTjr^il1BL7Q-k!=Vt*}ZYlFSZUSa)*>ARElRs9? z#TG7Gm$z{G0Kc??q2Cf8(_8#1zHP;8YtA*jUVU_WbY}GA=&8|(y1qeFH?_Ek#Y3ko zW7auCl{SK={jNa|reiW?wNjLF#dQq?4TMxR;EZz#53s=scS-5`f`oibk zymIsM&5P%+oxO4O>GNm3Jq}maCLjhUwFW~F(AXAFPfR+@z9@&Qi&$AFHIrLlUGxq^ z4}3ya7f0lToYLqbb~p2}v$L}^2)?>A9TUarXtf5<EVHF%2T zI-R~!Q&O5-x2jZ%Q?Z7asI3!Ho-%DIp*DQ0igAKbZ-H>=|5l6tfAUHGztiFW)6}_D z39{8qDpC-E=5)VN9{bMaqPAVv3BzbeO&COcYm2Rob!VTyg5ctToZpUVe z(24?!UDiDGI-XmT4Xl%}*G*7zWsu}7lcc+;P68wxH;QCQJ`1IX+f)#aBUC3;uQD(l z|8`@dP8D1gP_0bnCUaWCZ>heVb6M~UJ1HZeO%%>)IFQSGhqd2&tdt=JUk#LILm^j< z>+N#NGIVa4)y@XHH^;PHg!qj)SB=3G?~*8tOnpXk8B8im;_BE=b4kj$;E=4~c9>GsxY@XXU3kOgwq84}ZX%*AqZ)Lz(AmzEs)M7j=X4>ZqG*JY zmZH65(liD8zkz{Cf~hL!Ze@PgX9!f2yE^?lF&|ji4H|ZIIWE?6NE8hzd16^eWy!gB z4*C=+Xf15xdWJD8adXt8NFAb9bz}?X=tmd)bP^DBV5T3{x*;HBsnwIg0r#aP(#@O} zRZ3#0sHh7+trBd=3n(g~EP^gaSgf<>$xF9MbhsBHLvN+<+?Buxph5JtxLG2fuw?Hd zoCYuL7*$bhkp$dbxR-8%SWGQ$-sp7KQo{g7izu!TdU3hY>0Y3utF18IbXU~09cPV< z8iOHT{Zvw2tuMw@cY#-wiJY>n3USM{IB;hstPqP3I5=0!^^+T?Be`E0m=FgvQh&7_ zv_@qR`K#^Xu}|)hUImi-Bz)pSvrDRSeukZQmb`8EXOqCE5ItZ?#%qKU2FP)i^5W$Y zoNUjQ1AOBQBGO2dqnVnhb^O~kWCVkKQE%LGKBO$p{C2Gqbm9be6O79#yK%^^{dt&} zf0)f&bmu(py9~L6hje2atyW(!IM=U?4#=Da1y(UoQF*1uO3|U!l^!4ssY@~C?b=y% z7W_qjlTOTOnWvT+G@BFGcu-vJOM&6wLhuKjI(ou~1O^?mBCCkAgs(xUE~+VrH6wWAd@v(4ucz4I$SUHla|_i#`_x%e9!Y%&<|nw7w>0h{%5P zt#Kr&x^;N_unvzIFn|obB2X);Xt63Bl_}p-t2{v6w%=rguh8)*daP<2A2fJPMG#1kV3mTv^(}~!*skR zIHm+zJCa^NTL78{oOR(#kX;SUbTe7#b}HAWHdxsn)jV2Ycm_2f9Or>)2PFML6a_nZ zbpmWvA3+UB0j9(9#$asIWTBAM-`Z(ePuY)$JkMNIT4e z#Ba+u(n;O<%Iu9G4N{jY3VkU;$x*ttRH?z_Fj;bf%FH4QG(KBwZk|?1VCq!wj3eXu zylRk3wqtNJAnTQGOv|KxvyMKur(w{us-R#|=w6G=0*TH>=P|=?j>dUGBOJU&!QGg+$s|{Rn|xH^jSIq|&XmdZ+^AZ^T!69V@_&0%ZykIPR90TTd)6kKw=JVZYto@LyOBGXI67 z`NHz@*a)7#(03n_)qfqU-IZ9K+BY~-2T_#1tGhKTyh3(S>1Cl%b-{;*pkRif{8r(u z-EMaM=BB?MjB_M0?c&vG(V$h+=VA&+znSz1`Ph_TVR82)19zNs^9@|2{Zf+!nxYA0 zmT$n*O_xe}`c#uAJw86m?pW7jtM&~x`ti6N_A`li=}e~GpoySrb3Dp#huO}^fK#>> zaY(5zRm?S`#~!#=Of_gm)I>RX^TR4~mnHMNkuB_jlpzsNHqZl?J zl~+Aeq+G61K>+BED1d;rB}Q-JSBU8HM$IiuS{`3Q^1SDz_kkdZy?N;o<>Lp4AO9y! zFSq5}TW{4%au~gh;TKLZn+y;vUv&3oEr5v4^kSewJw|mLliD0I&hnXpxdFYrF$ptP z8;sXH2`i>Ds~j3DXfIl>4hU6xLe_7ut+~N>+S%M|XCd6X^#8c(y-x%?&0A3qhNBr^ zXf+)c76g>y`BBA`M9#-j0l+B&aF=FicJJ28%-vc^ns;sEWT6ekVVcoc#_cv8g9fP< zRfK60#z$;UOhU^p)4?QYmpI_h;b%U#dO2=x7P(m^q_O-=%CF1NFxM{nD$QQG$Jhj3 zP1eEA3vIJ3-N)KyVZEBP0%dlub!pbnY4s8TAP}cej#gjxkiE4=2%{F#@`pO=4|Jb#=+zR z)_NR|oWZyeHaCOpJ|Iz(TR^W852|r)mPNjk7=inQpxzB@7B5zH*2=tULD@BOQ%{r5 z9U~bK?!Q8;u3}L2pJ5g%KtQ`lxs+ZAlQdJkSU}XUcAFr^DrNj~_{wO6))6uQae5)S zPaJ8?=$w}<67_KVHFFS|+V+;>6zMzlo1^88y4rgIy+sX>k+aZh-9Kg*DA>ng4y|k7 z6|>4{1{^R}^vb2cQg$#{P&;a&XbwX;`yHWObp%msHZ~$Dyke^^Wxgkqo+f zI}K`S;Di$DT_UEag5dr!&GqjG)0&1awMOrQjMY5tijYgK5#WPC%+Kat=H-&vs|=bG zMaX?fCG%mg%foWqo0^Dr6AimdOpUbrz*v3_)9hL*9Nn#%JI1?WZKSx06*|?50xO?k z+uUu7HCVr_r%a%#E?CWO@zfI57fhv43Iml1m1fp0-K{R@{9OpeYN;KUYJ+?=`8XH5 zS5k)oiZY8~t(xUpx3xEDuEZJ~H+?k&5~euCABB;V=Wcf(m^OG(vv8b7^0X2FUA`zq z)nc3kG9v{bmDz?LX?PUOD#MxX3D_G&4!IzM58A;TTWks|nxi@y1xS`DEM*rL6*ZT> zC3y4cbC&V!II|uoS8}>2~EVQ|MiU*EkFZ7#R&H6A$5aOyQn8&SnR^`-NE&PBFx9@txTG#l!u2p}RO|CH z?XA8qXl9M-#JubTY3i>Bjq2pQY=_ZiqdGM&)38mqj!a83qqFB-cY1zr$EAs&`ytUv zy5dq7dgGN)3$Xi6pP^uF%q+tCF~Y}2&xL8zPg>ZonwdW0rN z$ZA*$NA2{oM`k9sJZ5g_Fw*>X5C3^~X;- zH97=>BIhTUPhD6(Q`bRD@YBTGbp5${y>NE<)XBo@Ue|ef!n|zy?I3FTiS2uKYWdWR z^FC?S5S~|Cjc+@JPA;FCvV}JMB&(@}ORz7PfuOP3LOGRfqp#d4Tdp1VS_<6RQ_H6& z?3*M`5o(oaOw68JK6Tc-4*VqBu)Uu;yL{@LdASxQfqgeSy}V$Dxz>)m-JKc&#+)LP z%V+E?tOtyx^OMW73(K>1R2%43Lp$rXx)H8#)VAVw=C22}G+fv7GrO?7V8=vP5r@%w zEr_;)cHDJ=oLXM6XhDQq(xD7ts=HIu%V#VgZ9iELYH@-TO0{N~G}~@d7nT<+$#Bsm zX!VzyUOqEza0a2|AY^)Z*3uQ^YYlfr)xv1A)(r?Krr+7=|-BM5nO8kt(2wUg3` zS3z9ejW}|FomxI)5u_7n(`FL4+qtT4t8q) zAA4^CAJ?x%rEP+5-O4$i1&;SYBuY~x!-%vx#yf))NL06>x5?Xw9<-5&&>mp$XQzWP?JK9eK!w8WR0}U1+xI= zYgi;5CD$sh@gDPaahH#UTm-iw+1ELyZq;Q7< zNkb7Yn9$0srKkwWo&i_QcP(fb9d5Y6h846MC+{-w0%LoV(rVaNqX%yu=z}#4Q|{eL z4_damN6XDLfRS*(#);M7**@tr&#vrwA7qT;+2+-fK?f%lSbPwC{3JI6>f$CH^el?| zy+W@c;BX7r90Bb!Drc5m+$N3dBWU}9`B6`_z(xjm3*^RvY{J-Rd-}~EYPV2zEN{PJ zvjr_v=3%;E9`72mD2K(9V>>Xczeh!my}|ZO+qq}~gP8f)AAYE)*c{QhP!tmUuudu) zc)cs|%f7jAv#mAX+_LND-IrY2y63XXuh<*D@~Q(@UvuqEH{X2At+(BI*WLGUUv0)X zl~Rs&r`B>wM+8nOFXXLrj(ZqXFg zYC;i)59>J|zxZ@bp>Ysn&d_)q0#49P^5kds}2gbUMIETprxRWR=;yZVWdkhiaVm?(nz z#tt50%f)s$UBu&V$?bVOUP|Iga<;5xcZUWcB@1p*qca3*X&!bMT$@rQS6rz8L*B+&RNo+r zj(S@iFp&VGj06r8EY>@wckGe}W6R`RH24Xcr;}J*5Dn(cv{7)V>DVoyt6Or$ypf~# zhuH=-ITpIwO0y36QWoe9MEvjLeZ5|r0~lQjj4-z2mO8ZRxY`Ddcxn~2sl*_%!Gj}H z8Z<^@ZAA^>@xER;p6Be0O%HSHKmS7>IVOTB|))_zjy-D+CFP2g{Gab@1 z8QXBcm>-v%S@iU^jB*(?Fg#jzp{W3^%v;$AVkcM>Lpg-ajPJxy2)1?Kg7(@Lv&;H3XRTk%^`3 zABLD*SD{;FaculpsI(clZ43&*TdiK>;cYa($;`=G3tFitJ^U-RQi5gNyaQAP0kM!Y z@Z|R@sePJ1TFPPF#zL6EKDTe+kHHuaP#Myc*&CEA1R-(&^tv4xFl%PUG28>9uynRm zn4=*Ey1VxG_Td02K+Dk*8E|@IFP}!-rg=k_?=izi-V3fOWew&_52stS?&{#4LI@&^ zoQc7yRBFYYD~P`Mym=Hqo11pAnBrQrFmKvc0q(EV(m6x7+q7v1;<>OO_R+#Tv&u_= z%SKBZV_IoQa`{#$Fz8fftf_poFu#QAh!#LMDQDWI79T9P|7jpUhe9c@2Ur$ppjTLs zE0}TyExuN_;Oz#c!wse&V2feE^0*mGySW90BoqMbJl?VZk$m{I0-B)=-n?#`5Sqi0 z42Bqd3`9*an>GX`1Pz%a9%-JgUrJoE|NJ@|`Gn0nr-UByn`_VKb-32m?-V8QZ{^{jRo|tNnT2JT(0w!q4Dk$zn zmB-YBpG@`w(_Os&$vn>QTXH}NRmvIm<|amM6NTtJkbjGJ2(&xB_dHd;{7JhT#2i){ zzdf=gZn&jl&@uz<{4A5~%4wmr3`i^6DVuO~sn1nJBMLB6)c+pth-4 zjA-yFwFRQu;jAMk$9uZ+#_)2)VA0m>Leir*z;O#*mGYoxd~{p*nxTt4Mz5r#d9T!N zW{kY|F%lde4zOEfTcY!Zy{HZ8i&Q4n4qCRi{!=G5R6uy@FQd8gx${z7P!VN>S59V{ z$;=}UbY?0I_2woJX3~02BEc?B}=I@Zx+LI7kVG8qzlv zB@87sa}I^a)TAzAr@=w>K4jZZEh-;r#LOph0Aq5>>Dfsan0mXjb&}WSK0Z@A4J3JWTj=;%h&?NkxBKDg91jcTKhJjbo4W>L71}J8Cuh5XjJUsJFTKIM=g?0zG@Vi)c zX`p#@;S%mrI&C=4Oev>-_HHazU3Rp0Q z^VEIF=~Zy+a#O9+`Gq~YS+ ztIQlB4XN!fH*3g=hCi<-Bu_|V%`rk6o|&s5vxGFS!~0cc2x;D^6k`z5{C%W0+p^rY ze4&(XOX=ykQV}=kO3Vc62H@@%+j8W^EdYwD?21A;-txl4Q`$wzO9551rS!S>Jlr~y zOzCq;+tIJ>>}c!8|8;h>6-z1LDY+)5WtpUaFzqEL)#*(K#lRqw7ZX0HTlk=|099;2 zYhXY>yX65K(0ktZ8XV9Uu>q}v0sUf{_y%+XD*^`d5LlOTPup}!>H%!ii&>j$gC}{buPB2M?UywSsMA)#jUCil z<_$NCmTBtqNv)-`1BM>|*A6BJg1Lf>!$;Hvbi{F+0DH4`C{pe{yID=_P=WoP)Mj

    g@8Kif3I=R5GiyNm=(o_&1e%2@jbuqYO=T@r+LFS8e68W71Ff1xcnQZHn8?#g zQHAImZLKFi?2g!NR#nlmT`Y?J_U7=H6vH;a2;pSIw;6L5nJ!z;hrr(Q!2aI8G0iq+ zO~T1 zVW%utCA05Lyb($Nbzh`p_7{xI>VwH_lUfeY*oj)DM|tqYq+^>i9ru7poTPnq+S`h@ zg{l$9PP1lb3D&<;S=-ljWQ8xG)CR9i7yY%>eyl9ll^SeN0Z;Xz*)e~kDd zr)=2{E>#t+f{jGAUD1ohz%t=EHd!x%a8OknnGh6M9)E{rvLDr!%O}@yvKjUxu#TW~ zV%Qxgs}_JPQB}Qi^T8to&$0A*-G(34_6APC1DlU8M2Yb0O19qC6G9xr&d=H-gpe9S z$aRGNt5v?&6GFz=bI6fo-!~}F8 z8=%mgElQzvdeOwT>P7RE+u8`lo~stSK`)x3t?YXPP?3`j%^8c%PDV$63B*JQ($O2) z_bclN`OBKIuI(`4>j`N9a)7a_Z3HF|>7a>_=I;1Nq^qYlyqN8sP95sME;fE_sQ<`_ z-hXhkIrGyW;;4GBGlE<)!Wh8*;yyp$r?gB zp)DQfKwCCIYi&m-gw)jl+1J#NH%z^5cgr)0aC4ihU-;NlUwQcWg`q9!g-<^3WlvxH z{uf=auKA@efAg(>`rDU${D*J5`Hk0I|1aC`xpecutA4fh8_jplzWoJzZ@l!c6IZ_H zPhK;#zUJE>{KXkRY=6!JubduzOY%L}Eqtfg`9#BC{rpQ$yy^BAzV}}~(D(AM-0;zc z8yo zK3aR%FCH3byziyt(ih$M&fmRb?pL?H_u;#*f6e=P=brrCb3R_0e&~Pge(dMrsD9u0 z_Fta!l6(LD>{tHeEidi7;qHgu7&I~K#KhF96VscEqnVw^P$7ik>zG5IXzR-Tf z6+?xw8wMv2FU%iLMsP1V^P)e!YJca6*KEu_zwNJn@sa#% z2kV~t{@>ic@cC!HS!jCSM>_5!8{cu{$&bH%UGXO$h;@JY)|dR%=R@E6YTcF>zPrBR zEnn(->(7e+{mA5kadZC-PtU*hQv>t2hC+2;_|GeU@cM7=`N*Z8T725tHNEio?HlHI zeEmm%f6ap*Jhc0wFTQ)-<#)9-&wb~IAFF-yW6AGb`>%ICGyc#c{rms-p({UpS>}H~ z`kCt={gXGo`gi~Goa|WVx$k~gXyA1tcRlazUuyjAH9xG~dhr&v%w{ZmLAT)=`%Mgp ze+CFm2!8&oeynRFA@|WW2QXeo2!IE!Ho)IHm{hU}*4<|K1Iw|liI9%>KrumUjx=_vcfAhA_oVoKo?Y)0fcje2+rw>12 z96kTRrnknP8F_BqrzgMiMBksi{m4t}et-PY{-3=6sh@xL@9%ADZhu+qp>x0eqlTyN zd-?e%lMk+&NIm+k7k_d0bEn%Lc*@%U*$;m`eb&F_ub+MOo8I%fw)H>ge9ry)gY8d$ z{}saxZ}{*}=Ik9G{QZ{n@Beo2gX8OVCJ&we!`k{?nJM?O znvp;K$DLh|z4UJ{`SFq4&#Ha$LA~wXSM2;>Uqzb{{CMt7+iPqY3Ib|x(6Qn{1yN4+7JEq@8=`t`?{X|)Z|s`-}d;|{_W%c{`Xy#wd+RS8{@#WY`Uf8G zekvK;|NEBykAM2!=iK&Z(|7;J=dS45@U}aCm`>dKJLmTAHC-MdgxpJh*xfl)`r7Q1 zzg+j#hm8lXxwI$!)y}=&{rWFH@c!3dzyJ1Mzxrj7{ZGB^Rp0pbCwKg=bNvs#zV)e@ zf8BrM9Sb$@xN1vV@2fv{SN1EH-0}Ote;oPtJqy3HK62S#-SAY$dEfoZ2VPuy!Gqcx zFC2e-XzJR*_J1l~a?#Mw_kHTskA3egkG^ErfAmgn|6c8De*K9*|LE_q5l{C=&U;ty z?AtE-cK0`5vgeoIy4Cp1?BQR%W&YM}+EZ8F`H`PL{pseZ{%<{V&z}GM_4|vj`0YI} zyYm;32hL1A{5gH#4V!))z4qiUj&=3l_u26y$)j^_-#IVX_D}6!|8eF8-~0D-kN@?# zFa6ukJbiHgO!q6#`r1qGzxQAM`D0(dzA+xxC*Svi=M2`rL_*>t1?ytY}h0Mnue%Rjd$`|$>eW2;_ z_8&j~_`m(&U01&0>39C!M{nBp*(*Nx+0iR%{_KgL6&@SzoI3HG+2*59{rjK(t|M}f z^A9il_rb*?;2)|K`dK z`KenLKKJ3fzW9^(*I&Nrt|z0Zd(MA( z!)tzg`NI7hfAQv9w?6Ohp7_wZxxszEI5O0|>zz%9&-v{>^U0}+SAF8U+5KC8`n;z; z^YwkDkG$h!w-wIL9D3rSE6lI=b-(7;x-EBo@&ngjck4AjyYLe&*X{e}{*Qg6i4d}o zOQ&aM?NZLTiZLIzFBXvk9L!0Yf`U8tXQ~ALLrL!nbwgL}Tq4lcbq!gFl-mNpo%2FqtHsz%&y8 z-4o4aCgb>hA){>26!7QY#_ z?}IU8J1Ei&j3vw^2tLpvScX7>8*vU#)@&dr8@7-WWFtA*aN=YmIiH+ttl36RHrB2u zCmS1gkdwe3vwtT~HeGa4s)?Lr8c!&sV7ToWV;*!6(91IjsqJCO;j@Q~b=4A}%^E`P ztA)1J))7*>nVdi|3x*8xAm2Y48ApNx0#?d}s}NF#&07K0z}vK&x8Sss%YnOC0_gs3 z_8rKGKZl{{X3t?r&ST$UXn6W>VtU%-8gdp68kGfc(bOEuXeD?ifLdXZ%ca0G80PABjP%Jzk zgtQPswzD*VM;Eg1fIDx1fh2@n0{Fz9UrGr168qjt2sy#N10{c%eZLIml7ZOepvz+I zyn+yN2kZM@LP&~z4-rBRv%GDDkRPz;?Szm|vF9CxkR9wh(BFBiFI|L?kFw{0p&wvl zxQ`Gr3I!w76LL8l|6Z6EmS#U8_Y26ReyA zgpdz0zUOK}NSKv#4U8Qt=UPI@=h=7Q|6ADi0Yb=0R?Z+Hgu&%+F0Uo|&2Z9i;voX7>LJ|1A0a@A_Yt7kN7j*Z>3-4-OTT&Z zO+uF*o4lo+z1j+gNFlvg4CxuL5rLFvDk=G?%PnWCWi{PoTP4?kf_%?)Jlc&--m+6o zzllAcv~2elz~`;xx$J!c4q3wO?J{S$ucNbfZ{Xt|{us_pjY1~e*TJ96*jB-XN8KGA z9oUP(_|(B|Tef_gBfgBzYLY8ik~8#7-Yi^e z9M|*3oY9uH@{oS}&~=gV;fZ8qXe>6KjE+TOqiW_ZmU$g!h74zUGE7F|@goycLo3NM z9gj|pN5-ORo<3I3nQX|)Mq<;!sfqDKbbKf|J>_ZPr7UMd(Q@2b+W;M7^ZLo*k%@Rh ztzjQe2gac(-NDh?I5`nd3{OSl$)N#Ayp0X(US8M%mTO}=3xP%QMrT(yRB(pKsE$Bc z_Wdk-BPGm|jkRtTnPDgb>*eEdb|4A$LKB)Mrw2x3gZ}XdRcLWjJUTcPO(YLRkE+Ac z!G|SQm@x~cy9h;Z9hew8nvBP8j3!58V=)}Z20kT>`>oKl9vps3sZfu|CdiQWNK!u? zPuiJybn0+)iuXxm-i}8YXAts8Edd7e3&5s)4r~+J!HK^;Z)8mUv%q~oo!iA|=d4-! zZcxp%6OVLqW~!Y}^RZkzkcBAWEKdnM)rDC91&mFbycnetddRUJ6yKoZznHz9pl=&K zw2>YL&;$!cY8xSs)R9R{MrE;DXg3T($80tY$Fl8?p%?O&oii3Yd)n2eg!riCbk}fP zbt0#NO6**|L_V!bkz&{%@|AgeN_VnaC=F&(MK=UigVc!-tXB9F7Ia?=Eoyw=j^#p~ zy&?Q%I-zbzP0yf1M!~fgiKw9JA09;c*)I#)POhvTM(RX z0c!%>Fvz%g$b}-#*@QIw{^ZG%=dd@(&r>#^{%a&e8(iO%)?H&3?^Z3^R;HA8&3V&Z zY--IIGdkQfk+zMDQE*K?=d^~kR>Z_G{%vi_7*5&_YpoI7f=aeA3U+IbrfaUP&l@={ z1*St_+*-_9uBF{>m27IQmD2QLF=wVRwoz*nSR92lb=I4#qH9`(u+~)6XN|Dd3QGvi z^wmUdda>BrnJ@@65hP`>H-6RF#Z(s8jWU?=9)(oH2S$dp$k z;CyJHH4K4%aDOR#tF*IK*-m)rvKVM9wiB3{k}XRTfUmUFI~Tp8Gzs^RxU4=iPf2Nc zfZ$X_A%~U^q8+6%_!rVzf!zuBb%gbzNmJMcT8D0v7I8MlMtzyy0(6{qeu9Rm~ z%1TganPPTW!FI?d=41(a_HA6PVU6!=Y&z)9REffSX!A6!wQN69hMbQ`AES)w$5M1* zxxwr~!V51LspW^0V<8(CFw@lwnXq;j>+;%xHdd%OE=ZhNlO@9EA#mGRejK%B$x@7T zB?h7u4pTw!Zr-HsAh4P3tOVK@02`xhCCCnd-s76n+)7}h+@vn6^VY4Zu$9tNi>VUy zZ4HF2TGGNe)q1!&25POJ9FC#j(MVg8$t(t>nf9lVykrdleWu_gH!uSu!3D0T21mg5 z)ez3uMHypv?Zp9%T@5+tW0{b#+nsYLW0x}vrQ@(i8+N;Bw8DAGo>axy)K{KOTiGMJ4{MXnTFG>jTpJ2qos8)E(9xj;C0e-nv*k(;$CgWFyMIH*{fwty=d4P z-G!XJG;VDvpI@Yb8(a%6II;_xo`N{G$RycD#!S0V(_$-i^K#IP9}?`*9W7r1InQ5P;kBNjw-i>Kscim4Ld8?jxGULmvXpTdbBEn*MtAV$pyesuC{&aR~Z@8 zb5zt{17xfxS1@E;he9ksUXw^ ztb-Hd2Vs^&ML_A*3;kKP2%mBqHX{`;T*#w{nwD;piSaZ$+pbuw&7-H4a=T2klTcbQ?>~) zc2(^Xbye*W_o};u<65>pYgCkc7mSqVfWM@adyg2Y5UABMD0Y^Lnq%ckAhuHHE2mTh zK*QaGdVc}RV=y9K8<$rdE(3Fttp>>hhpY_C=@M81%0pVKpnq682XIMoR9D~9)o~zT z6)CB`YvTZ2HOhOs91g(ppilWWQ5`MNJY^e2e_wxJ82?lyKLl&ii%`CSQcK zR$NozvhKP0Vp#SK1x31A!a++)?nWCJ{Q+d`3D}4NCmXh+MnRZ@i$1i9gy{j&JL^wl z&uC+iy+s^dr1eY&1%)-(G6^;}SKM55`$xKwp=s$;!CzO|n)KdGK013xdPxNnu*0-lDYt9j{vjN(!+lyWX?2SxHe?_pA z4$drPNN{P8Y(~e%2rU>Xg#p{BJgy2P)>Q=(KT$zKRUlPl#1y?zXIHo6#&ir011q0- z98$5}wie*(3Amz32hkjvFdk(Hej5WYxLOHPp$GGE)4_ObgGeKW&~9@uX;ns|wIZk} zLZqq!q0r0d569RCH=fcN>;M-+Js^{CRD#-V+BldbiU8$0NDfxj&2dEp>+cKqb@X*h z6br&El&yt~Ex9B{sbNaN5^>6Og`FI8svb8$qb*)y5ZI(Y>%;)aq%MhTP6wa%GS+C5 zWR0?G1x|Is+@z)x@UVVxavJR|>e5*oSPU4{`p&MtF?>4|iywl%!`t)u+n&xYw5+Hb zi;nS^lHIBy9~Kv#3Rlv0#fa|}PJ3D<;1unUNE(2Rv8Tq2Ss1}4#+Y))<^`Y;T{~#n~zRRPbCKrCKD5fqT^8gro{C4cyyFLfbMRjP0Q)Fp_ri& zu$+Db9R(h#A-DRL-+6ASP%v^@C{(aQAe1vJDZ7Nz#f+c8(n}Vue9idlt!jlfRJB60 z>IzkMYHq$Xh<7lcw1D7^9oG`rpS_x{WppEN72qmZS2Kg9Q&CS|Y zX*P?2l9W=6%&Z}`5IEyFtaA185^!ZIDcDLCrVXu?2beC@av?z}t+JVdI{6@2c*vvD z-YiR2zGmcl^=+$Qf3Ii`^k;p<{nYgB)inbE1I!Rw-L8T5pq_B?pnnFX`35j9sn zyViAR=IT{+{I^E+o$x92osuzFfuchWn!+KdJ*o%vz)7GRbEzBt3aY4Ev+Xv!_IO<^rWhYiF{>+g`CC|8qDg!Z}K31w14NXPk)B}dLOV~5iLjX%ie6dJ8Iy!MAIXDs>Jd`{*F_oO29Ev2Op3K}S zL}cFS&3rIA6rGABViU*;@+y0|s)tv3o;TN2bT}4Il;`8FDrgh7h3AoG7QB4!HL}6B z(sNEG1-%jtgH!2&NIaT^bL!|g^}JzY5oHaN4i0&gwnFTEJCt-5uUM2c8A*%)5%FTe zteCn^YG@}$bS!cMG6p#YW(-AmM3_wZ5e z?d;tTxi;~JPEJfwS03M#Z(FoVb{j>|HrN>;*AAYGxsvd`nP=u6JzH*Sp@W0B!rcN{ z&*53Q!xb&U(?7YbQxQNK27+%SI4PgAGjJz{NK$1YdPvdm;7sv}^3I#GA@gojwHY^6 zwHcpZryNasWJ@U(AO_&YU%HUaXLN^(=C+Z;Q0idc=b{u~*z^n&tU(sFn`m!t;hP)l zq-6VjZVl{xo9+0ecG?WKqXjA3TKN<*q=1cw0SQNWnIsq=S{3~uct~*Q!PF8EmQ1E1 zK!t>K+4J35sYonKw!mA%8p8p$@rovil(2xIr@}1ROFr#oU9Yf^p^Q#x#3(BAFIz~* z*LPXjuv#GjEaS45%A$lc{sml?-nSAVk9XbD99)I7qUA)h25}U9VQ4&Z6yjL8TqjNMdPTc~tFvrWkbK?goU8=y?eoT39j?^k(FdNO@Qrg5*eN7&X+?1-Ye-wrBKLTL z?FOCts8yJa6f$umZ5uAVux#2fG6^eg&K43`NHtcPpN_xHu45)nBo|@nNXG<%UFe+Szs5{u&x-k0`b_l ziWsk)Z2HHe9Q3iMrBGibBOl&MN&xU!F*SMdrP35ufRgTxj=mK*@&p>4Q?)O6p{HkNg~}K8EYh3pCOR;;FlI>8=x^~;Pp6%*_@!y~ zLOv7LE@w}`TM~mz%lz~VlTI*KEHzbBL78Cw zT%q=Qw&9fWa0!uCD#9%SPCK{7ktR5cXywPWQW9QaZP;$*gD++6_jh!3%E>N6S5}f7 z?-`TL1og}mV@a=94f6>S&t13*6+AufXlHXr;V_Utm#YTgxQew#%hELeI+91~<;-6I zWmiJz{;uvY{t@b23p$Lf$1xB5$}E<^_(iX`sa$padQ%h4sD2+Azx9SdZnx?O=lka1}1^ z`L&&0`%wqi8SdHF-NjR01NS23^#k<&XQ*tG5JY`7az)nJ;LHc-)3U_g?*09cw{a>u z6pQ;a%5AX@&uRsqE;U=S6JEA`Lnf63t6$I~ifm^HzNwwL76>+)3uQ)++~m zYAHFOjzIs*bUqiz9hmna+}Rt_b49a&2kf<()U`nwm1AQzY5Y^!y?J*)4_8+8d9rFc zBm3LBl#18k!>V@u%~kFCA5b+*rz(NK^{qB|5zU#*Ts2(+t^vbkXmH9hW7&BvRWft* z+}bttyzn7nBUMojVebP>-7~4BBo3cLJ6%LP;H2Y^lylID(EW3t^&P41^%l(vT%`s7M0YcwbioszfCMa-fD_XrgJ$ z$DYj$|6KZPs=K4J`*g)WR-qL9IDkP5Y1=D#WB8Xi?Nb2%f(a4bn8%k;dX>qRJ2(Tw z+6C*Tf-Kp4Y6};*4-R6Ft**Aq$mx!|Rwr4ik5vus1Y$S3P%-wRZAv?aZl|-}oeUjb zVZW&r!3Vx`7M1wm(cOx@eGa9>;J z{x%H0wAs_#>8K)-P`Om|UQ8S$Tm4Cr$73=~<^U6a1x zdL7ogB|rfcW^HCUDBz2wm^lBu0rR7ZjdW3$vph=-eFY%t>*(Jf#y+C|obUt{gw;1)PHGZP6^+nKN8)JDSz9dLa{nK`dxF zbIyP$N3*sfd&-VgUeHJ!P)2|RDqk+Ku0vWYpV|Yw8y2&IE?>;DNagFYQVfJ0s$wmp z_!}T!P_DpFPIBp&Nf{XR7W753xm?hYtH1x0=f}4M?pj?b1Ju5=Yjtj=N*T2Tls;ks zUx?Nqa9am$k!#uQwo$Yk)3t0F+<_h}fu>62JTD+8v+)-guz@}B>cd{icKQ2*clp4m zxAHntrJvK=L=R5( zdQQ(l{!qfcBC_C#7yt`&&p{Dl#>!<3+Yw$9qT>}2MWiTa62z;DthY!Zzm-iu#ZA8t zJfQ-CLeDMei!@wn06ehc6S!ux61CDgQ5s=%M^#$h^z4-cmY^dTj4%$^BKpesic0R& zkc!Q)3t+EsgUtRr)C{p0)&7L(X`g5z2HMch5vG=1YRZ0LX*Y!RLf zmp@ZTM%;p3MqCtGIHR=uq*g$`?vBn*Q1x~Kn?#9+rmQIVU=Lf-?7(yvlUC7{wxA(= z0TN=kR6yH^0*{>B>SXgt$GijMUUbf~cozYv>T_`ra+c2;v$K2nxQMK6di zD>yJ;%q$^rNlh>y7Fe5mkPBokxXT1$Wc@S5$oglYYGEO;0&RjW1`n2$Vb8+kx3doL z&u}LO#Nz#`3dnX;1!SLA87{@SrV^3`>1+?;n<4ZSL0zDfXSLQ+O(+d zENZSLZYlt!OwL-+@;Z2z7xY5f*sGbYc6-TjwTxweL#v_PZlxp}MysuifAl?!ryu|5 zn=tl(;nWiID{yCA|>rL#tQ zPRm)d4$4?8B#dxoRD#a%s1sRpHXEWoElg{x9tOn+$Fx0h76?Wg#8^)yn;IjG36sXl zG-uIqjXYQE(g9flFMwu3PC6e58St{A%vL@H6_$E`e}BJELJL^flt{vic;w=)tfZlR zUF&i&`7m$uxY5 z1X9!jK@rNioq5s0r$|;0U4+>FkYbLdfKQQP{ShNIl^Cp)<_x%=iKU@JU0|I4OSyf2 zDyPpGshpmkbFzkR^DziJE?DcTV_X%+omCaay-XGC=FN;@3E53Ac;bGJAD&_d&$W8>qro;PeAL;6EBe(>TJU<`q?A; zZYlOCknCH1?&+K%w+Q&cQ91B%Yef|48!}!N1?9sP9J^RA=2dGwIsrq_) zdf-J*yPGbCDZvK5E@iy0Ju)9e31f^}u%&W$M`cT8pHRr`)j-^&0l&lEH80VB9ZnW7 zHD_@>jb|FYBICpVSJ11vjQ{I&ctGy5E`vGGny&GOIRXGLY6ZeUsS3U<*dPJnC{KFg zjnJ^q-c*XlOv;@ft7P%Y??-u81KkMVQ^0eb<76rB4h1RG_+cQ{4<|jeCE?Dtu6=Di zA=|QCxI+piY#pYl3U$w}3Uyzoa+aqkg~k=PxM7pJK!e}Mg6U>a#a0%z40}-#A;mcO z&=H>pGlC*Z@X%F2xbBXQ{XPpt#IUZeE)@T|!j8if{!1&e0vJguA$kZ<0UVA*hMT4> zmRRE#BSoMM(Z>oxFUGo8as&2+`o^u)-*F>`XNGkg8w zz(Vf2qtU}gqWi}FNqcr`d|{xYzjuH4u_Hs1voRD+hhvG+$Ut&xVj|(;9oN$iNY=5A zfRlrOl#P7Ga(YVO2}24`WYev5>aAIrHZ^fQ$YKFW;e6Pi6ljRbt2_$gz!Fgq1Fhzp zr4bP=oqdGThN7ou-L48(&Z!DlI#h118e9RC3$I`rrPtXkK#o*+UIuad-#}ZM0 zLJ5hren`aFs;CL_L!#$QG9bu+KsXwC8Wi_Ept$b=)(NH7x=g`=JJ7wa=)D)2g2UM^ z79AEpCEF!zu)uY!%)as>xsr-jK5rQ9bVxk7h!a*7F7B)f7mupAxcu=YbGT({JQ4a` zD)hL^uA;~rRdoMD<8hD6E!bTMZVWYodIqlMO+(aUJPCjtGiJ^;Y*WT#qrd%QVI)&GP;vRQ!@z`5G$i1x`wn?PSXc^#8t8(tyLxB13=oez;X=r zw3p3%1pw{o4)=7UbeaKccEDuh7U^>kYQ4`{aNPcVQhr`B7s*jpE-|HI3Zp!7hXhdH z8K=fYR>djW({11MbFXYg9ZU6t@;Q3q^d?;r4Swn>U@3o-^;D2OK`DHNjcZA+8LM^nHMdD|@q)zOS4J z6t7AoGKNF}DaB3N{95pG{Hr{96;Kdv1oz3z0oD!py0JdE4s7i_AipXN=0b1`_ZF0#`KxY>1drI|s*xXht^(vgW(IeLfO+(qY%K3+mt{`5%ySZh(D4+15h1Y!pH*_dk&0(qZo)hT#M2oFocPm|IzG58eF>r(hgRfKz3w zKTsr`$};9mBrOWpq~Z@1o4m!ddOfL?#n~FxaN*(x#J85^D68VO(%I$PR#wa`vt<<) zGvHf*P&J2$rKZ6f+<;Ff-)6;IWgq5JSXmmj1AEHgBPBT~F@?%1qT^IyYXy+29MwQr zB$XL02g4dLFBL!!furZGEQLxIx3(k)+j}Z6_&`XR2 zfpc?^87_2NcO27k^#UrWw$Op#kE+7i^8sgfTp0aO6dzRs@hF#ZuI z_5lFGbqe%TqQzFVZd%pYT4p|PrqMBe4LI*Jg{SFy zS?{)?0U4E;N8V=dd0fOs5d;dxcjM4Na%3W&@Fj*jiGizc;5!3P%l8}@O;#`%{h$N@ zQK}%_1_N{J$Ulu0CYIDYe{fz1?N{ey zBMT-Cl`AvBqwLp%Ga8Z&OXn++J4)BZ;~3;^>(D?lo|u@53`diRqmvk$zKN4x=RPig zvEjgi1t&B#01Z%5^Y95C`VAJqlw6!7Jh{q6FeQf+!hH95m-#+~0H+~PFLN>ockT<(cnImNWoJ6ty4yNJ#aa5u z>1gX}>+lgmB&doO$@$LfxjAEzeT4f$aJlhDHoaK%9iy=6 ztmHz*iiN|8AP=%u{~pyERSy?K!onVKSOT{-3Oxz_x{IeT>RM$J$By#SVz(j)`lfUBX|dkVN=_Q`u5()fFUuwnTXQVAVM=RQ7`<%Sw+q9s>{ zx(l|3wRn7pleV(qm8}}_Zi%HK(lE7vXX%vB)2ZMu?ONq2$fPRk4VpBKLT*KDp|5c` zcypJ>aw%cZU<<%I2%8Q%^MG;{1d5T>f?b72>Rnxxgjtx$m5xKV)$Jd%SK+X|!OpieN+|(MG0ZuOu$`jsr#f8*i^G0K`qt;{151^7*Ta z8n^4|Ib*GysHhn$iopExnT?U@#00w)4*I!)HppEfW<})`JnjWcA?30vU9UWL`%Us5 z0C8s4z^?}IqR?M6w<`DyK%s#^@gqpR#u}~&NxUyrfzd@(fsw~>fd+o@+ylWwZ$&0! zTD(+*1&TIW=z=t(&s&Hiu4UUs!PQ(FCH*lxHs5iidv=~Qk;F{m4**776(29z$MVA^nyU5 z#!)uuxfuUZ6|P)d)rn1)YE-&ny~e?y$T(OEGaY^Q?*isyQg%|qU#$8G4KFz0keD6$^7=aZfj8@4nm5B)^W5Jnam@#K;*eMhW#V+0w`Gab z;pSzj26-o5(gUY+jSAPjO9#U_Gq0~zOi^iLbq1Q-U5k~sq2n;1RwLSUjzwal(BpOZ zmY=t5OlKiNMBeD^!c!5N7BmDhZHejj8x%$hI^po z&h+I|`!1zdD;+j$$FvFu`an4g?JK*Ugf@{MDbQb#aLd@y`1PaW01I1)Z2}<^SjWwt z_9$7n%0p)124S1PNrU$Qa_pd$lsR6}ns}oc#TY=ICYlG7Cb9;(2h;)aRpCP~(>lcVl}OOO zQX4EfD;Jm1a`A6hSTE}7EcNHZC;k|d7l%SD<_9S0Y<<=UvC!>ipiG!RJftBLX_$Zbq=uRl$X0HztB57S>ul zy{8@sWtWD~Ic%qmS{)qmZeNmIuzy}sthj%5KzvLZA&#b5G0RSCqxuJM9HYNM=LOIB zaD_CMP-q~$X}R{HNz>>^Q87pOqktQVF{77q6;=$bCr~Q#0%&WPQ4O0X`j%rQf6Kwq zo63Wacm=YAQEy77O2)B($;P*w(U3DG7WQe4JtHlyX2hS8lPEJc6RykHI?hd8SVrmU zqK1uzG?Ej|H$HodT5i5iX{&020*baZyQN?c;dah-iw0VVTrd`yibaM7l2eiKp@}gs z6+x$KGbz5sHqf@_F=N2iUz-`?H+X9E?dP?b6ojLJn&=f=u;*_Yj0}!MlS5On!*ti*oiUxF?xwSb zy_a%2d!0hQ=-PTQv)5U4a@K5Nmdlr3D-AG+;Z_n=6$2hG&>T;zp%iW^Q&lOqtz`JX z5J(-ns%qd9RNIT3UenM3Ke~kBud0ZOUFF7MZNNxSRPHUEbcKT~7alc3u!rXfi%H5*?ZzMJBwe zfw+#BZX0>aHIjNJLwV=XiQ!~yGI=nfoPfjPG9F$$EDu^$~ z`mUbdF1E!XO`XF`Kd#L13D7RU03S8>2l3%>gUYRlMO)qH{4leBI%6bl`Bu;pnl+an@Y8#d5{? z#jgdeWc^mvr0_n=y<}O zzJ|?M80?FV3Ev568a{%QNY3Cy0((qiDl&=tTchAicAICfio{s zqfx(nIAkzb6)K3Jc*&=qz^k-4$dne>1}QBzkazn|+MbKDK}HLOsGb4u1ql@mJA^R= z4|HmwP|jK~>`+>F4Eitx=UC2x4lNV{-Iktq4Ljr*Ziw=GT+s!u!7&SL>3pw}rGg1D zV3KL79aQ8W-8S`1D%^<{inW;hK zJsr%zyLpvL)3$!cVqQPqp2u}25hU=`W4TJ@f(Ud+TrRsX;t(R%=sPS&l0Kl6vSq-wv zo{Q#!gyy$;6+(u0H-g*cw=h29R7z4m?+@m)D0xK8Zj{32ZhnU9@ID8I_q8 zw=T!M`--k$c&u{Me!Au?jierIn<&`F6XQ!hq~&T#z9_{PT26pHD^&w?#V_3teVW{s z)!UL=kZuE&zW&`iT=!9t98rCckfd`+02o1C8k+20EViJzvUa{JnhKtRuVJ)SLZ4Ep(d8LtY{b+sW)Fyh#nqN{i8H~THxL7f$@1R2{Q4P%~4!PltxyixooLQ zbNTWLE^XX-gn}k#a0>Ny1+P zrCiR*ny$F>Pj+x=Z6!`gfWA`ZXZuvShptRgQQGDt5Y}4#BtmyxE>u@FM>I>B#L!J` z)ueNYy5iwq2pd0RN>}De2q0Y9WZyUjNOzF&)txcl^0;ud5h0`7c)Yg;h~Ra0ZC1~` z*3-Lsgt;v>V?PBikDsv%wcsHSf7Bbj2PX zqu3m3ADb^ZW*Q?K8hAYxy>{KO(I9r(F$#u@7O(@Rn_!M+U{(lsus_>DyXdHu`GC;J zOP~%6dz)U$nEvauXikPVOCtl6Q2`G6dciFg{s?cg06<`_7x=*ifF*Du!0UpxmUg6q zuWNKwW>O*1H#DxQ{Ui1s%?Z{39M%(Vc6PC_NaYa~j^$7_++Lgo4h^`6^^?PJs04kl z&7}Cb{H8G@W9szcN(423P@~#R>IP<3(HROEg|wA13$q7WrxOSJTHy>k%?_iD1FeJn zfxB45pHT0aBIrYGJeC+5NJgfH(SV^gli~r7%32W|DycS;;?@UcIm*K%DXBLq@#CRQ zO@kBT2V=v@p%|L9up?o~N7bVbf-o;wK7`R`KJFnH?qy96d{^qo;PwK|nLnP#EqD{1 zQe4ND#i5kei%&QdSs#9`b$^47d*AVa6yi)~uWg{*3Lgp{G_a8plCPaApgW(I$ZxK+?? zd#^U7103(wCgu&>F${aJHeD#9v$Kt*UkAQ&@B&MAsHe1}B@Pb_;QPeb&;S;gH(VVk za<5D@5gQuBL=%yco7KA7IxwYPa8`j( zDX!NZT2Tkr=Y%cJ_k#|dD3*n_)@6W?Z$vWk%n(GbQLE(#vOzG_8rE7?40`maOjGLQ zO#5;*Glg?m>-f$cxIk$a12$y7h!K)x7z+NF?GTW?iZeEWm!NJ?0E^bn8+b~1K#M37 zLi##7x>tH^;gd}yuF^VCaG`L?d_?IFDZK=`x9<&bZ?8zjz_^@K0aUoIL)%%S&hZ~n zC8Kdvf$e6K3Mt*EBfW8hR_QpKH}ck6sdH4}t%iW#iQp)x&m{O|VS~iBzYc$T_wvG- zGz=nq2FPcD_GlMNs3;hg1EtcMlq-yBT~%$tmsGU{zf;xARCP&v#>iV?_#?O52-{%y zq6cG$-fOql6JBtxU@hd}mI=1;;`Rv}R>5+?k`k|SD&}+-t~i#PE^M$x+nm?ai=nht zaMGq#a;R*Fxh;EEFR+_VK-!~0MQ}nY?rSB-zytw7iST(vRSzu|@QP#SGBZ{IC40KM zJHq&9Y1u4qu}DOM<|OEqxvdGct=c`5$i#$kC~Lm&f69aba!``~(kerSSuoKWdJROn zTEZj8ZX6tmj1Nc0qRexC$5?DUHc{@;who)e4b>aKZxWoeK+4&wWC7NKju7-lN;)*y zhrp#ELux=Hc>(Yq7H|kYB^v2P6NDbPpZ#){;4)7FaTDDUpCG}!_BE7k(6YJUSUDpE z{yT=_Xf5IXj*iY2=+6#*wF35m{*`^I3dk<43dl~VK*qerD+&;N#KX#jNjMuZXR~1S z4N!z}QrYe7tW?H&QFm+COy$_6!I8XvhgHzx-2#SS+A6|O-Yk^ISjQ|3fTWEq<@J^u zZi+TRoOi22R0?0)>ghc)VxFXowdI55LB4=#t$=p@V8w!e^dhsiMV_u7uJ!~vktn!g z=W0C3qV{w`nZ1Ec6Hwn4&IQuJ1~@#EcSoIjfsEIl?%Ye-K5;sT2EiJjQCsH?7sDBc z@|JU~v{vCmR4%C2%LQ$1r!8?^3kP1XL3k~uM@h0pNt&~yo}?~k;f)iu1Uz8?e{R}9 z*(LZC09Btq=DOgX11SKRAg;6rp_&%>@sG2_P321DW+R<5i;lqt({(LHz0oN8RTV0= zR)tFUd4n7|jy?;QzR|EYl+$Px^(Nslj|B_285#vQtlh;{X3lh6qhQ!tXJ218d#2}d z)qJw4;LA%W$IGrA}pJ#7q0(RD3t z?D|AP%VW0;EoEDChAqI4C#np9JVn64n|LR%5KgW*YXlBE`2A;k?Mc|YD0U%Ur%2~5v z(;^JNxLt9q6|NOd*59LuB6p*{7z* z$D>p6WOO_-Fd9W`07%SL`qEwd3`mVvZ$^`Y6BCDG=qLnrm4(lt0r}p#aB@aMy6L zNaar8$jr2iw9{JXE3{TbIywkGT`6W^@D|9lRYi5)K$e)tM`{5nJmlr~VDV8B>JH%| z9Z7H$XnZ*7pJOheeyyT31tf0mMcDPQNSRd9Gsa*{nv9&G~3ykd?8XV-tqbIeJ$ z?z~k!b}Sff%37-c-0cKhM`18lc?qRS`s^G&it>5f2rY5_@Ytlg za4gexJl!##xjjF0bm-XF(SbwLx9bPHqbN}aA4`g|_+F#*tNd6}q+TVbchP~{yN~oZ zj#FI7xZ~3YyBEzn;)icHr&5!%$Hor!Uyt-1l1bfg`TqpC#K@b ziK*CdY@A)H8X3hnf9wPgm~jL;0#N+nAvp^{Z$6FptgCqO9bu5~giVb?0IMy^i=ae$fq&|(z zWh9b_3`FAUMDiu;U4YxvTs%kxEB{(Xc(O6O)zqkh?T&@ zz*Ge}o(=@813otOz1{S_E>GKi>wzbhZQrW4-Ag(=97hcXhhle-1q>ml8}AVMg2u3} zL&yPGwXy*h(FRm8Y%2o%pexhpO5+Q%QqUM*GTG8b+EVWz8LUGGxbUVI%{Jw@-ZqMs z!^k`YYQ$2(bQd|@+eXgN9cmzb##D4P8i_}#OBKHzo3#e6+JbSrHjzK*9-bWPir(Rx zV-wa?O5fLeEHaioa%1k z@$m3MZ~p{Tw?mYWj7-LoiHSo|yuq7w4Q{c9u5F{Iz8Nd8n*|1 zk%@hP$qzDR+U+v!Qj3aTcChV8bYNs+;!qIaNWpHy>DfI2WmY;$pj-ypBEUpdO14!p zBbXLCF4AsqH{3KQJ*xK-vL-W_@$NI^u^?pl zE!Ft_derjE${0D+GZZq=sS=!$!*6E4Rxn(+g-68qr37DD?SO-k(^El5-Q1*T2@S+) z8f>xFv2&%hG1Y2aP9o$=QrRBZWm>~(Ykisx(-QVq;m*}C-CB9vhf`nZe}EVebch3t z+pyovvW+XO<<=oI{rS9J$b^>;guw>n6u@R>1G1ca9;gcQ1M1QPfxdbGfuJDD<$M1MO`3I{LbNSK$Wi%~UcA zmkVpWiy`Kq5nc{FLJ-1?wjv-Yd!>}hq^qFB?3HrzBiU?_y@jJH9T3jx!U@nuh1&)} zAKle^PKnz_>4Dae+_cI^K*!xQ-p8{BW{R6n!}E-*G8zlmVylGL;`q;h8Z#*t<^I|8 zJ`-w8XYf$(Vs`Gj?AVdm$f4=J;aKW~sJes}!_I+JwFCKjKBbzDou%2#}AOFZ4 zD^dpr9o$gCnj4Ht)zHrI=naX%(TVAyBwn2&kV27Nd2?m1GyS=IDl@M6Y`RHLrwzx6 zP2!z(=gMq}sp)tkI+Prm7>mTH5d%|^ar0EKhE)!ZPeaW$dEVr~3R$7aTW&u?O&;B_ zpt_(z;q?m5DpM}g^b<5vGV795n$@j|(#&HGw;A1@78VxTvuQ2E6@PCv>DcCVx)!zUjTBVF~M--d9sx&v3SEaf6*g8dX(>i134CQjn){2HB z%9bKcN8(0qCIp9zM#kemA)Of(vSvC9@8->n;ZS!5cC)f$q)WD;&6Eo0*6yGd2->4L zS=}}ZvwP9$T~ArI?wa!kUc$T=Js)hxFQ|4%KRc-6k(mxCiWTJN-~h``6Pa zRdEnkRK-CIsWzw3D+r!14CTkI5M1aWSpYYyyP8|F3t&CEC^Bef!L>9!V2^i-dRlJp z*saQYJH8Is*x5KxQ~7`;8ZcTFmuY{8Pls@dChICC$YtEXhY;59cCK@h9rN0w53kbr zQo$ZaA+_2oFJsu)nKfT|p6DY!*TBtSGoG}KOcKW1d!Bs*bHRbn03&a>wXN(tyIEa& z(Bljm35RS$4Jfw(YPF5(qRH*8YWel4%THPZiv>7pEwB}6TeG&F&%+@q_!1lQM!^kb zY;)cyfHilH#m;*fXfQYxx{h{9H9y;uCuSN1Dr^dt#QRG&NJJ7H#wgX z^$xk{LF%bz07F9f-H1IYuF)6-!PQod3-kz62pE&!SbbwPMyP7@CFm9?!W} zQJXh)jp>558QaR^CJMJ5mt2UmQ*vN=J0?T}(nb=ANo{gE0r`RD*5KA6!*S&bcV`wW zFK>5dvCYZ)Ts7b+Ti3!V7Y7@K#PXPsSVgdWR6ZXS0HC|0qh~qJ*hhUdUW}whS~4C2 z2#RAGes^Y3?!G>)`c?r2bTGUy@H}|>hn`D8!#`N%efy5otbszrn&XNGA)4AV)sjjN6s-D?794N??6p{r>q$HCTMFwD#;sYWmniOb&q-l^QNb@05 z3_gO7kVVT@1Z~<8a)fBfLHgG5{rRY@N6+@|%`HfqeHYWcnSW;f`RAX1{`u#hfBubU z_zf<6mn`n(R=Kipk(@wWaUxpvBt&p=Y~auC+`03lVGP{4bLYI~*j(tPl>8CwCV+ zgmjq-PZ>F#qWi#fktLu|o&Fqn=}NF%J!L*kg2)3x{+$YsG$v%Kx2xVjbet1?NC!)u z$31)CU};?T^>?B?6z|dpA@lbhlzM*Dkf$&M^4WB((NC?c&M&_*e{Jp6oHYyG9^@D{ zqucO}1--O0pL{`i=93muPW1Gi@u~Go4P23E%rC#3tvo#s=`(PHLFqM*(8}Vu&8k8~ zsWv6s_P;H*?f5PcFF5Wg>>XZ6b(A-DSdy^FOB<_fbv#eoz^7g7N#0a@k~hDr%bUn@ z+@Pzx;g)|ne5tUpq}H*=n&SPuIM_<|tcaNo+j4#8@S4qt+05Ndug5F8c9jX5KYx)x zIR!=4CL~4aebPMNXm&{1GijyIgO*uPHLijoQ9K|~G&2;D*GIRD#G0;MMj*M%69-Ey zE75}FDI#dXiG~%^?Rlxx97tBktFzg`R>Erh-UmB7+aCQ3EX4W@xXptW4?#t5#LSLZ z(%50N2|EjZnOPt|8*#rw&e)Et3mIGmQbOh&nFN~%P3b##H4Xk0-wBob+xHoG622f~ zhGc9*utsH%H9M~MvyM9-`Ve*8o}^2yC+YHSx^%JJuA)WVR8FPJX3V0>R^&3@@%9no zesh707mJHavH1d`60ykJH&;B*YFj-2qC5%|lc3}FB3DYuQZ8CL?%hO7I{pv`IWFPT zTndM~4@(!ZFu~(X>Q<4G(G{B{#|^?`NE{{PxVi zp&I-{D@vT^12T&Y8ZsaSzpMAm%;Mt8D~*|rjhWe-OY_Scjk%RqmhrYYg~m9+kyBTS z`SK53`)5{_ZX%%M4dtWrn`;0$gA0_6+0C`J`Q=%De~eeRBBatte9LnaR33OUIaH>0Ryh3?(Rb9e5i|E&z8!Jl-H`Zo0_$^Kj zD)00iVRRAf^xXXQna#zG#^MZrBU^w;U!ODcohS%d^%{#jmr6V=OTeM{^_6A4a(QX8 zf7ObT%G@=g!ou?U#?12Ue0tL?OH@7(r{PF^V{PW;nT;8K)0ji0g7_#6of5>46M5v} zTD22qH=g|>0k0sdGS6hogq^16+T4p+X^N+LYJ>K28U6CHY-ybBIZajWh||nk!Njpp zi9<}Ef!pT=!T)|uxojp;;JbEQ1r;hzb4=4K1!Z~?`(r(cednm=TGCTIO|EWy*xqLL z4n=*kTts>Df);lNk-FJO(gi~B1mEPQs;7!rBBEl#Duzz;kR`B}1wQi=il6D2u5U6t zr$E#(Z8x$zZfYgtEYr&(B9M{a;{EX4D#EK1OGwdRCR&5ZtWDu1NJ^s&tEqE_}?hnX{udCd!K zR46whyaQbqkkGAwBS(Ff}bDbhPmK7G12oju&S=d)dDj>YAAj_B~o;ZEdLLMz$E3Q#4{ zmP*Q#>6k;8ROh|gKtLisQ9kZU{5{oe+_jnb6UX1duBLd@8+z@@ z{e~ha@zoCv4kI5%9I^A7T|o-iW6qKiMcI2K~AnN&cE82U7T51 z0;I;s72TgcsJ4{3Ye7BF4K>fm@5)$RK=2yNPwqk9Khl^7wp1ZMT7r{I+K3S{P`QL-i zzG#bD&)$M9K7^K&u&7W4B}~u3)cLs}Wf$|&-~98zyJ}7^R^EZsE}pT4ZOgVF)KU6z zWu8vY$)34!od>#H*m$kvh^@aBSzDHG6%W{+C>E4QY_gC%U^|iaGJhHFn7`#TWyCfO zF1?6*`3-iJqj0@!@%lholn+kT-vTE(^`^%d-odNj84{{TS^;=Z(^maqJ<2P~9AI+}LV*OfO=ZiQ8teZFvkg!FcQmeV7Ch zQ|=o@D_yzo(+cS!%lCtX-lmI(>RN_r4#5a8R5w4NfbmI-^3PDS<9f-0KU6ozMlz75 zIh1lhu5M8lBRy0%hs0P9y7!G-^zXPWD#HX|hLd$0!r7Gm|OmXnAD*_xi!Haa0RF?8U@_debDXRDkZMn>I zX6a>u5*8d1GB3~if<0})2YH^SnlW23>dAJ*;_bk5;w&ckRillR{FGp3nnSK1hs?&L*TdVSpOR8TZ7U32zm;bc z`O)c+>aYkrTc#;s@U6Y|TOOKO zpI@Ax-7wv-5l8k2-J#{b+_2%qiAbSeabmT@hU>>HLOcS5Rx>|2bOHOH2I2C_E{wLd zK$_4@8Lly*Q5+}}6!1E2QttBO%0Fd=h(w_kS#6fEsEjAlPq*?^hg`HdVM;JhKT0o< zkrq~E`^6a~KY7_FKP5Aae+rG1*ImL__;l;)p^^&sufaQiNh~pDB_ExyoH+SQQkBq1 zd=#mOul|x)T_-Uf7|hDr~-n64u5;&7ggD zoO(3s(8UNB21QM~p>8y=q;svs^|==127ZHMI7%R~`APqkoAYb)q6E(~uS)NtVRL4A zPOoio;l+7#m^7f>D~;!eKk2Wm&CRcw*Iv`0a>S+Gs_k_gHse7BD^=fzJgdn_LE9jU zNlH?|XHq{&wXY&fy8F-#A)guD!!IarvA#1D_^jGYa-%7HKu7 zlXaP!nDx9}Zmb4fCPnu?Ll#wW-oPK56do=G>-~9AT~M`c2sHwHU%_k!6-#_kz9Z!s_*fR|R;N`USELtnGDkyf!r@8kQLtiiXej zG8m*ytBn_Agk4iSj$RS-At_3i0xT%JQ7EC zqixwEPMpy9u4nm_XvLIfaS-%^{!Kqn2tz2@iQ|Urn6o!$)?OI9bg>9OY!2&kzHQmq zPT?DGpO?Vb>gvBjNheP3qa?V-ynAP?m@w<9<5o<#^aRUy+otQYq^!H6^k1f{+)QyV zC1^VVy57B;1PVgl9W=4S22C7ueQ9QK@$LoOut8I-S9o|D-M!Wj7v7RAq|Q^#{e;E& zvCsi%viHzXcAvpd`CuP1_uOPV=p>Y4VvQ>s$XaczLjRk!TAlvS3@Wd@6FL?QO>}}- zUbl|<>e|B6%-U<_i}SCUFF-D;DK{dg68}NQEE11`kLjCIr5P+^{7MaD5{Ao03<(^# zbgS4!AsQ}zNc<3A2Z$EV1-eY}JMAJ@=v{Rf4_Jali^R!z?V_HaA%)**cf$&?;@37X z+A9(bztbMk>%VBeJhQktzb^WLGsR&y9KJYWzA%QLcANiW9RFyEe@u*+!>tz2n4|*C zw=MqfsS$HHPKFh}FI*ZihZCD;PLG(wOccCAHS+Ya%OmD+#}WSkRJ(JVkQhf!L^%@0 zaVi-Hl_Z=bmPG(Ld|vH{sY-g;Q*PP1QAJU(`k|`Yiv<` zBXQz zwta7@Uq5v_qA)50@*h22J(=ps_x3m6+0_$)9lwR``VPCzBC~DzR*OYg&~ERWAJpGO^ZHBWBsj8!@pWHYxTFZWOtG!dekt2*5s#UoP6UA~)#7=IYC9 zh*}ztnyU4<6O!~bn?bT|ZUj-p{KVXdu*;12-Ih%r25o_(7>}9@*o});Vl!q|+hcL; z?eiAb1K*0G5p&IQ=zG!S-?&e+#wgJYwze2fU+7l3#}Xzwjt48vV2fidXcF^k{Qx&` zfWE}Uj9JnNDL|teF~@vikC{$@J5!eDT^xP)gSAPXD&DLSW83|fi~uMJ*(S4u=#?Vy zAO`2cu&{_;xpd`Ho&Fqjbw%C;>>ilyF?owkq9)^^7lWFZR-fW5H#RLfhJVS|hsW1g zFO)d@U*5@G$>Ob>$Z9s-2X*VF&sZ0?C7&f_o;TjURplPiPD2>@ao_aWwV7+z7B-e% zYRoUgcstivUEI8}u)N;5zOYDvPX=W1^j3>u;C}XT!xYy^UU-79EcjL{%Q35cE0h7` zr>}Add@BfCca&9pLWH@-w*olUzLg~BMI%2x#H+x!f;bL{SYB)SkZ1+p3Zx$(mAx3( zTKbHSm928`OVw!E+4`jR^bB!^%;{;NyVTP{_djPAy1<7M8}5FKgC&ww!?ImDYF%yc zpHPr|v4hMXNz-m6+Q0T#vw@UPjdtG{w-BDUPJh#l@k+>iv8y!O9WQY!w9~c&T;Ggi zt3~%QqhN=LUGmJ*ORKa*Exoj{Ay-AY8Ibauwb9wsmbe;Yvu~K3<=Qe)6( z4mW;z#2n9kPyqn-7k{{>)~6ow`ObqM^7&AicJ$s`9cv$tr}JKjFFhy@&**7VPxmyb zAJr$dcu&{n{v33Ghe%tIyNk{ERuuS21uqxi9g#KWIBsI@MQ)NXAFUKvYw10v$xBE>mc_HhsC*2Yl2NIg_CX7Mu%mCwWj8Fm(*IppM)N z0r||JKL5}mFPiYAw7&t1CZ7}PmVNF;o|0hN9}`mt-|1>-g)ZM%ER;nslA$RPooB5-* z%)~)+`bgy_f3D8nHz1POCEE^MuBwho04^;`_5%gf1QT@?FEzXmR;$&m(B&|w!h+}E zaL0#rv4Vq&kclQs)^A{zf262iuoC8NSp@GQo)A8Q%f)yrNi=sD;|&Rwokb5nbf~s| za8r66TJ+=Orezld)x9`tWAxS2R6}* zO^ag3$x9GS@c7!w=JMR^=C%2ynT5s1+_lEWYpY~FI-^i*Tds$=Y>WN50N_pt=g!s|Dy*&xn_bU*9RKJYGs$%~DE*n_+m%2VL zcGSRA_l0vh?ZrROZAMnKug+)dmKVA{1=i7L-D_plOlYPjIqjzfcaHh)f46?b@MH; zXbZhWzX!zwr<&6>>7;~@2#QKKXBv7&6avX5S{qE;-c#7EvqDy#mR%}=7xg+eP^R-D)^9_!Uq zLq^PTrB=%j0Urt8rDyUZ!RQ9ExjwtLu)0BK5Dn%Hu-+Ci{%e8~IZnwR+_JXY~`ZIp9 zNG5hWbR!m<6E!D~8xLR9@PZZ&Z1r3@AfM^3Gu8Xb!WsfiLgaZShS_RYO6-HtFEjdN<7n4-o5y^s6t#tCEK)mmYdvM4up`) z?p3M9bW@+D;E_UH$e#ODj8!e&Rt?mv5U2UUC)%*XLgqVhBaPOCE-O$GtE%jrp<)ha zmpP$nT_sISBVPdu3wlaMN5x1ls}alQRcKfTRoHc03Qczz9~$NYFs6HoXIBKE?_3q? zP*)&bnYmi70^PMN(c;RLiLQW}k|Ns3Yc>ZLr3NN1O>wA_JzuX2F|XjB_jh}Hd)Z*_ zs7E!**Jx!NxT~M3wt}ifCF@#B5abmx>d5$W{N^1MxZC8wJR-m%rR4PHICJfUS6Xo4 zn5d1x?v@&^-#OXpQE-rn?r~|NQ>2CT#J2d^10_1tZDY`Q`~28FOLXi9(%s{ErxK96>WJo0*l$xgw=%I+?psB8AmijYAg} zi|N|*m0k~NXlW|3qKXE^#OAL(i!|B2im9MDQSqosX1=HE%L$aVw=n^SH3;&!mZLUiH*tRcq?`Fh#0YSN}w2WMwyZ_YR77RbCb$kD+A zC}NSIM{5pPY*YbSc1|wMtZ&S($pt5^Zb(#jY^+wRp|{6YZ!GZlWK|6%Fq?UpbkR9t z;5i1hH1rE6Q?(vEtm+jxcs@;m=hmpRDR8=c$VXJZ`+!GOO5;3VD08S)Eod@5?R!sR z{lh(p^<`bGYaVs-)OZ~nw+bIM@}hN^*SXD1&q|nY@0)FA#hr*dOXJZl^2oL=UuNLS zY7jB<0&(0p^sIeZc0~R_MiRNr4!Mx<7bkGB*z|%p9#xA4aXx(gx*bRXI$(*r!=h1p zJEdT5u}~EqBy$y;ldMeI$~$a0W!WC&uxd+5WbiTGn61^+TVG(?Op;uNdf|(%0{F`K zJJZ%v)VXF=7vH+r`o)p>;~hnbUyCAzUu8=nY(do=2p#lb9(Fc z$1lGbytHr&^*qY)SzB4z$W-=_Kx#zbE}ym3`*M<(l_ycMAJ{&i+s7$_3^l@^-@7(5 z`{L$mgWsU#t2GTsBA@I@OFYa=fJ}|m&9xgDaQS#b3O3Dt?^#mCbcPodlYTE3-4)VLcCcbaP`CV5b2l-}KWvBp*0? z?qEGsAtZK`vK>i}{!X$r-EK}2N^{p52rsZcPluQi6sJuX!$$;YqvN}XR@$&>`kY3o zmBq!GjfE9D&6DLmD966NAK#)K>KOuEUY?)r1}n<~ol|qyvU5Xl2p<0gJ_FTG995hA z`BPvqx4E>c_Plv$^#<$15_0{;h1JITI&HKiw0vV@aBTcCMIWI@@B8Pjsk221IV-T} zX@;UJndvFIf;#}{%CU)w+9et)0IsZM=r5m!J?3}#19*b~TARPV@T$%brC{qTvoB^x zQ;v#6K~fqsS03cbJc-_s7Cjy^xUe*HW4^Jta7}Ml9%-JmlEkvNao&MCpP(~!JY?CJ zU%ECw*I1h0xVgfGlj!}F=sjKm|5)yX_be4h%-P1w+#IR8ve>8`|8+==%EAVk)8O;H zkYm~pE8KQK27p1TUY-}rn&m7#24g4@hQRQLALdFxIeXNQoFTxnAy&gORvV`yU*2?n zkR=t%XmO4zUz=ZDd~IW;K#s98a%79-DI%q^niG#v3mc2;jhE-w7Oub6Se@^w!(~h( zCGycJzHd0SH1ld>ZGL@oaf9A&mNb-486U^lAc==3SJxI^p4phE6SVc$);H#t8gmQl zFY4S@7ri}Ar5gOHPvW=L&1;Jbvj>&cw<4LxFX&it%n-^7S6?Aa)b4}p2VM6bA|J1E z+d(_Gt&oq8Y6V zyC=6c-PnxRTVf3olOa7hq{#wsL5r@`)oE2q-4dN}I2(0P zfTT)bAzx~JWf}9!c*Z$Z{p6^j(2MhU#CiBWlsz>9sVaw>NX5(KN&RiOZfWy!% z^{|Ikb*1_l+7aqlCRgfVTE3>PWkIDL2KI-BCh^kLt{g+*{b^0jLL*WK)2k*uOlnv8 z_p7-kg`!Hu(#zi03=&EcDup7IsgLxe;kpUsN$Vk3jEd=UMJx7PDL=z?vn9P@hiTy~ zXgPR0R%t`BRRUES4Uo<0Jqqs>5-T?#rK*z!f&N0mi}adIJE(#Sgmw~Uax@C-G@&-3 zmC(@C#>LUDDY~d@A9qDv0w0WhPTj~c3gM%TMiy74Q2>{z)R6Ozg=rTRWVlW)Op1fb zl?@=H>m_`&QZcN{!J-(Z-29r&t0=MV*Tyo&r4o59jYhD@BNUEkJ+;T@%tKE|o4f!N zD=CaZ#k>9I-+R!Sozd9d$*m-54LGyQlI@BWhLt$*z7f|IbHPgniK@UwX@4cRFP?lq zzl(_P^!9~%FBi_w1@-UobX`XEn(B58|L#d|`$$iE+mwD^i66}T;XUb@S;i>F*{;b zqWRUd#Az8W1+Z>UZd28;lH)EF)U@I(x`G?S_;b)*!1P=THKx-?JI;DiO`U9Kvj)`< z^hQ-o9vbWC5BJs*-Ybs25p(C=y6XF^m|plUnO?nL_2rZS-B0kJJd9%k9BW3*4kCv|W@5QsfRH!1OZW}F^2>==xbn-ByKmfxFGrL7GtoR< z2nV@bmLAAZ1>NWP70mG~2hQ>PzVCZ3o%xtuqe-_HnimgqC^c67)x#GO$vzA!58zlt zzx3N@z*44;drwt;cDoak`Q@M`_8$mOp>NMza8yeyuI?0;SlxRk@GZP^$y=MyR@>v$ zeounnV?7CiNA*))2Odd52>V7?I|-cP%_<^v(Zm9p6+(*NyQAofqjV86h@8}iI(Ge* z$D}nS*g}xbWSfM8<#{rg7Jtm0j(U@AH*zYW6(##-)AcPpV?RQ%xB{Q~NjySPrmYrI zaWp)$KyKLZ+ve7VVM#@fUK$=We_wHLZ*Nq>!bpP{QclNC@*S*1EDT}9JIh+_U=;S0xA~;_OtJIHhp}X5WXTT)7XL zLF=g86ZhZ@g8Vh#cyQbU8Fp531LvHfLzZPBW6sVuUX~5uYH7zyVkOA>MMBo=@h))= z;+!n2RxDG5$Turnrfj6jyUh}NyA#445G{||@h%9VnTRbv3H-R7WZ*Fc92YKciqffcfVvB(d`N~8i+~_lU9w6l zesZRO7o_yL8(Fd&oYlh~!U8+qIb>hHecw*VA@KodJ4cLz{N)G}JcA_;xXS$QB#eHL zg)>^EH5Gj7#F11+wK`eFb+qdGzHcjm!~@ts934|m*k3cb^#b3S?G=uY`wU~?-)(XL zd@F#nz_OCqA&;?!bG96{`AhBJ5L(Mz@0mH?mTW7gT_OK@vtF2gN9*# zUf1?WmD57=4R_V~N}@gCtjhH}h}cSNIi0;t~6>-G;#gUv;3}dRn=T_?M~&% z2K-$&3VbNVB86Y7+gzBts(b4pp7f1OniQU;yF=NxyV!yzrYGz4N7;g?_3?2;qM*Ok z#18AIE@f{njthVtM*yb0twWC0#xK|DFF}?uHV40F1ykC5`M1`l*x;&}pNjs6z*QP^ zLQPQjeiZTKy`K_G@F(9*4#f(PPSD>yTm>;<_O}0^d;qhX-3z+d9-wR}y`e>;(}5v)_xr+@Mhf#^&7ey17ouAeqp7GjnLs zNw$N?O{~P-Wu_IId(89j9WlET#YjYXaj7WTwi0ryZZbsBjZw>rpj%I%J|szi)YkIHRaVg$t7lk+`t+9;uL~9a2>3azORnf1ddu zH-Vl!WVseueoTQ<9)Mb_%e5m0ywQ|8`e@Y&_Ix}Q8&{!oAhx?wIR|83Pa14?r~EC# z@{jL~B;+!!G?s^1rW|lexpC|U^z_1MJ)tMDHrJCn_}jWz}+p9(9oTVsX?|x`b zy^{rNy`Cv&;i0L6dgV>rpw2sL=>R#YcDM2CBG#_du8h^`j}mJoTVu(L^%9oV)To?( zrNmVl0Q4Cpsb~^%*5X~wZkEp#2A+1ida*xyCr9VScjBq?JDnheF_9V!T-_I+@9}g zZvTirx9?A7nK5IR9^~4yb{L-cz_Xm#3*vzb85fj-2d?ijFJUjb$%uI)Aand`fSX#^ ztXN&@;4>%NsYj|qbFlYFU_9566lrtWm@3QX=--bu&q$xSU zy~@)j*U2vP^4SB)n&*iB`f%0oPK4;M4`|LEHDtWUQ@N`&k8Q4r+jcxEp}G$85J#{R zR(Oal8D`|1sDP)!#z%cn)yys~%r9?rtp=}^z>+W+!*46uVdPHmWWM;!=EhBNOD>N{ zYTwSe-St;_JY6L_PVj$YcR&W%AM7&_KC++{d?4lQ4s55@T-P;oa2}bS#KeuB#Kixg ziwPOnSndNhqidO1!LT5pcQ7qp{iXv%5_6c8M9Rq+*vmHI_*L(I$Ev!R0XSzYj7DxUP9 z!cR%nKTqPU;(tjEp@?kP+ekxL<$3dKe}M&-zCk#Wy^qC1j!H&UlYIbl0QWR9$5{hn zOj6@%KOZbQT~Dp2yT8k=r})m;4CE12M*!ek0X)RVs3Om!ahVWDRC@v#-wOD&045)B zZi={ZZ_9)~1zNY@68Tw`(`zK5x~eoe!Ji>DmkLFb=+xxcWS#$2)&n~2LD~f6Ow@BM zqDe47O%c?Tgd*O!Pa!1vpI^a}9oE_tj4#EMW>4)|PL&++%pb~tXXO{Ce*fXhuU)I- zB@`0j0oy%$ewRT;sQH<$v6B1BMTYh$1Mj63In2lYbeHM!;*^%#lgL=;No2g05gFn% zL#Zw^zG-=MI7~+=94V758aT}5=hW~-+-7))h~qA-o#xEy!ichQh__G3umOv)mAHss zMy8KoYs~O!j<0mjOw7DC8fM>c-u>lvO}J`;8ti+IML*`^7^R11{dXe?a>#U5)9>M!0&k z$}w>*7}>k|G9OXryT5gTYbf|uIt9*m;S&U<7T!YJW!znvS@C`)2`UI!is0395jC6p z=F7w>uC>IwHEK#T-iR3ndo0@OcxD`U6c$VEv@%`nzR!|if@CFU9l4r>bU~zd9z9Wx z&%KTv7dpiaTXCb5!%_WPAJ#4+?8@Z$be;a>6eB21W0S%K2As(&C_8f@2`6z#=SaG{ z${ByuDX=V~(KajMn(sb8K!|18{SObMVSQMwfD0O1n@+j=;#`@efs5F7k zlo)bY=mp}UMd}ZdiUQHa!;vepG9g;tkx0nWzKc|thE$+GN-Era;)|MdHzMwP?#~{= zxL|S@SnErN8;p9_jad|Y1LpT}182j^OJlGavljI9)PnLb#|_FX&&jxToUGy;Io=Mm z66aJ2nKhxeajKeZciK(ga=o;bM`W2a4mtS6!ce`eVbFlfc3$GY64z{pkW25FPF7A;rE9u~g zkho)S!&@$BzQOFobXdY)pdB&W0fiCOQt(s>xUPQj_Q;NFHaYA1KT1Hm z`qU72Lq2MHA4Fzmh`Jp7{rmqvaynKmDRRDgxO?h7%k!)U^%!uUu`13Gdx&oN^!jT{ z*H@NbYaq%~qcOL#G_$a*4krgV;#TI)OkTaUA{dve612oU0cWdfU3xzS|HzcsW6dfB zE{pMAU5llQ+zI|~zUWBv-!B|s{zG8N!ujP;y5cA-}ZC08Qvz&^XR1l&gf~S)wo=cWHZCSjl#FhXh$Cxs!tLBTy z{M{G_!WG7~?orga7%R$n*{u2@28Y8J&KD+XW0M&>;60y9iam502Wz61^I-a7PKsup zZ_~Z^X??6oOO^IUSsG-A_&p~R)PSq|#LxFM;E-F2b${gKp~iXMv!cj)P*0#fY{=lW zr+B+NEOJO{>LFwYRh|sSnx=rzfR!OT)12`^orm!+>Qs#-&d=T0cT*d=UQ-B7d z_0G&KEi9Kb0OcNooN3^kDj;KwWwDa)i9RKtJge}N{0bhM*=7+L9Z#;$&#ujH$NxYEY_3s!(X@o5LN4a>;Pu6s^%t>PWYLoZPD4qb z;*ctsbXv8H{`;&D6LhKv->uBUKA__1>uW2^8}rL^G6M5`Re}hE^6`-@)-n|Bk#TyZ z;S8d!Zmuq_%*-{GC{AzMo}^%!0t5@s^D6Gtp669*#2A@p?tqS7Mn?6`vW6<6vxZ(Q z_4zqsU?kLPdxnR*=!A5SKsf{Siv+yxs$lQ_7U~)K0A2%JSy*5 zch)pxmUO~&QGbOyD$C`Y4*HWwxGoVz{KRE3Z7@X}rt2es7@Z8J%RMCZ4(lE%NIU2% zQapETr$$2V*2>>6RA2|cUns&>Ue&<0jxP(5a znpB{wM)HDJ!?#SVUL99aMl0s95}#Kk!vre)r^+Uod6lC6YnAJ=@alo0Q!Av)zMczZ z#NgF&@zRG>*m|3{9EXC^HeI_i_0E(wA-eeKu9R$OO=GVE6j$7TURmF`u{OWnn7dZW zSt`FP>nMmWtRqQvkYM5jx@VnLN;ne1X*gk-e2YI{eSjwVywpSw6bM}`10Q{d;wroR z{?H+Bvsp6<9@G^b?i&X+P75|69&kFrF~Ng;IRNnrlmL+7Do(tjFh9Pru)!a-5HRV| zUU28-wjZ^qYuBE6JTRPk|6JK+0Jtethz1kE{gT9l)RtIO!p@X=UGL*G#C9D-h`)Md@+DA(d z;2C=J+=PdtW2zA4@)!JoU%fs%Z#pdANrF&6%`tafi)^9dePk@s%_!K5S!({|{qDM# z)~1r@`kmX{iKoh^e}xy$FR?V_a(z_@%b4n-K^Q}e2T!!X^$^*C;E18Fat`A%M@px= z4saJ4K2aO1sT&KNk2qwB9krW%vamrODG^IuX_-B*e)-)Qd&nxm-b?+5yR8l)C#2oL z18}t)pdA6^&>(M@#W6M_B@ZYaaVR`ZS6I2)fig#&rrgJ#iGw!F)ZOhdq$5sKzHpI6 zCieo8hR6|a0yy`|%G%uO+Wb0JZT0qucqLT6;*qU0TSVFfL=m~s$`*M%(~92RduT~o z6hskSfM<@{4tO}DWPkOK57=M%xn0pzr6QuwR1l{DFU8xmTd0Iyr{(%rDP(=aCy&F1 zjDiTJcrMjgQW|3-B z+NVog+H3bZX}H!eXUxpQhq{=)X*HYfZ3wRiu$T@~+<96c)e9VG`k~jay(({U$%nB9 ztrqi>kv-Owk8T|wtJS6o@bWdQ6kfhYYev_nr<+qZFMGk8Q&%>p<~rl{wu4U&bNG{(yLa6*A%4g@U&dS8irDZ#4wl2-QaXq@})!uwnyib-9Rp^^m749se zdp%LBn`WZbheaCoX?@A5CmL|Nx}P;N*3|bS*fCDzNlC8zI-(@LSDY6CqzxT{0y<5%vYAD*I7}CNYA)e zJ(@496HE*>D3&?KemY+$j=ic4La4!gShN|(UWIb->ZBs$Q)LzGu>G|BLt1%cWQspi zRy>ZqhMmR+IHOfyXHVga==<$3i7d@kOrbAxGVW!M<=bz&%@p-hlH6`H&bZ4xOtS*C z;*VO4D{7HVg2;q(h4khjVv`>+jDc^d2 zNMQjvMpL(NuJCNCv1I0Pg(`;>;?2zD)Nk_0J)ai#+-77&`^rWG`)RTt(+xPgm-Hg+A{W?c8Jt3J- zpHP|gtT;AT@ZjBg(1~njF7qgN=8_7DEH!jqO;`1tXO~$lvtvUzbhW8aE?+bbSY#wB6;l)tvM*JYMVlhM0MC580Ly%Omq{w{ z2PoI2S_x=%H=Ty#QKV3pS=5zEeCbMia1R@UtY%a`z$uIz-^}Z2g(nXMJ9d5X@NRmL z9G-5EboEA7we1sI5Dlv$#j`xA3muM3$>Gj4b|U&-giMf7duw(6S7U9JH%575b>2kR z5fvEdDn&iN4C$GYWOxgSHiLN`qEI@gV-zb;a|o{|YdTPI4#^fViE_YV65*4grnH0t zxY8_&=%5f(gVHj{C@*4Lr3JY9P*Ox{0L4-=r&tI}e*qqe0NrEK08+X!Pv@4{m6tzv zD57Tke`Nk;7me;6*OnjIbJ|w&A-LNt&ae8sREgmpfTWJ`HAYj}QZqvCmdPX1gwF*B z)>atmPwUG%HdgdlM)e+-b<%Tq#b*q|aKo6{n0CzGYMnL==v>B_h#`(|*o4m*Z}*)t z48#{7Jc1LbzB6e4B>tej(-FJXVR2G{8~>xK){wEN5k^56#FmG;Pa1~tDN#4RKPBq! z=OtoIO@WA*TA4*3?4fvPQXqf`LsL+JK1L#gQpQ~_{dSi7&!JZ1mAi4 ze7`W+qA}h(;DP4fzH{f!W1@L{KPL1|q#qa2haX8x1)gi~H(F892~qlpVHi(~()dPD zV-N=PIHETUV9_vD@swd0ckbLVnxe3d#;#!)O#^luqwl2gw(%bHrr$6I?|{}g?L$mt z;|cuZDg2Rm4jONtH=Z<*nEgCnl2+1DkWpY6TkwOyzww#XzM)N{i@@v{FgtD-gP+CV zOan(^1=>^$^z#h?aU`kjaufy)!$5EjE3vo7(FXYI=S3U%{&{0*{HkI6Eq>lfy?(?n z2L9+MK;IthW9T*Y_B~*?XAI-~hwJ3&X13#&Idn6K6LZPkiGtUd=LLI+u{^i(%JR^M z&YZlkabunN&Jv4btHsONeaHH`IC!?6Qu z81Jcu;|J6*k*{IEFpN&viY$lEdwk9c`s4eou{3_tFb4Y|KxiW1O-~U*Cca=8#+MDl zm=PuL%EE`l??1b9=g!B(@1G`^rSV@kj4v3*uhHLMB1ZlV!|3}J!|3}}!x;QBnE1=s zogas*`91{2$!n48v{+?sWfs<#11q4A=nw-yLv8YpdX^7ogVLggXj>Hp)~e_L4_?5Ynp)T>wCf&``GTvuX=yq{U=}jZ;ova{r>mv|Ly<&gOeZq z$-nWXXaBdq`G0@Re{Ht^51;-G1#i zM*oC>`L_dxak-C1`wJAB?QdZ&8vpUmoj<)ZV7yHW+9?t=FR<(MU|J$T{lWPmS?_vW5#?TV!L&-cJU&H`JL4;2+L{h z_SD4G!~p*}HaRwllZW>n)H3vf$Cq3?3UFo4oDHHdi0I7ntYMsg8c1p(P2esO1)j&~ z5dE~?e4lHbz$MvNpoRc5^IbT>z&sk z2zGgFtR@IHU7NlHg54DZ5bfN8pD-^^u#-TvNz)a_6Dfr*kJdh0PNAa(3jGyDp;|eG zCMRpxUah|VYIW{avtmwurs{+CB5%BFG|htABdE(i*ba|$0qHHwB~a#Bkk zJ%3jmx>M-{Ur(|Gx;#2Dp$K%&faLqa9mDu%cZ}?WK3*V~J{8A$CD+2-yr5RegucI8 zQeute7_M}{bPT%F>I}eCIJi8?#(s~h24Bb#>4Z+CBUm1$C+ao)S4N+g#fmUHS6y3K zGEGUC(VEFQ>Ank-_&=z6bbMeb-b!E;LGStno?SZDU+frl>)?*fx$zE}UHE#Zb?kl% zXF66^eX(PrsS|?9`;4PT>@+ir)j*+l*LkT@hLm(IYkmZG25=QPHe;tr%ljc!bsU2v zbcp+=!Wa~wD2TC-m#WpOCNvTVp(JYwU!CJtpeIj{GO@@u`vxd?4oMH66 zkM=jTw>dZXVOS&hItTNj!>~1`4|Z1~qa7!%Oop8yO|IZkw#apu%mx`m_O567u}p^w z*~CkZG67_0Cfn6c%p#cvOhsWBXKg=;Jeh|bgqFu{tD0bO5II|p-0kbB?KBl=*p|mE zSuIQouoG2dn}rSAYS0@DmW@aS3VF~d1qzZ-mPT*Wj7Zgrj-=__mMY6Yfws4|0$+82 zkn)0#BSFw3yB*>AdV8xSQy)Sq4-i$2_hUaui0SY-Ct&b>&R81%zxoX0KlB;KpY$2$ zDN&URne7EF*Vij`SmLv!60-zv8O7)nKG>1TZ#-EA9y@0kN5I4Q24CVEJcn;!?QGj2 zH)4yzL?TM%@%k>wbXbD4^ahXo8LND-pO!C+spN=x*1m#PZBw!Y2Cq^bd<3dZ*LPfB z5fnxzJ)1lG%EF+fp6f9yR&1WHnPacec`{d)XE$P&_CH?(M^V*~$1UzOeWs|8&)sFd z6DSS?KRIr^qxhGI=Egg8=;pRCu;9Y~ly+qXZR7rh_>F1#9pd-D?FWqXc6!|~jDIdR z>EniBU?cfCZe8rN#a16Q`$vY+_g#iz{A0r~zS}U2>xNBfCxWk7;lMx ze-kplrab}q-)X;p2F9~~{P_<2`A+=#FJP5O+Tm9G*YVGN{PC&G7l`*9!+7|MU;N?+ z@sIBZ?5^bm@%I7jd-3PLLK?jQ{snkNtHay>1eu>gW(!u~PvW0V{IOKp8veNmM_Kol zKZ@54E46VLx<}hEbh9#PkF(13#Mb4?^cI`4$1hEeZ8cdH zSG{Z1#EM!hA-%RLwA*Ua3+$b0>@>m0$73t8#)z5e7cuj9940g0w>TX*RA&BjAWlz4 zR$IKOZ~!;|Pk(}y@m-Ut@9!#8Q|x-;`uBGgtZ7B}F)>oJ` z*0SO-3Q(V{AKF?gvO+xZO-d#O2#~o@1hcu#;C5Oi^yF-|9d_EREsGcPx0&T7+uieB zL}XJa7t7!3uuhu)xZXYuUk-sx?>K;CDV8WHo^8JbAd3Jr)oho*9|%Ag1_`fB_7wvu zGiaCNs)5wAa>Ju%#nCQuWrg4@S)smB1=2Dd0dSauSmF*-gQ^$YYq@H}h_xJ=-D@YA9!{4u~X_+TITY4XQ-`wIp(0B|@kzP-=r8!+DP>o?vu{$Zcd_iKh> z{BWPq_nm!4-)|a*@qZpQ`mp!=+;Ib&nt?la3{Ye6#2+6u23C(7#tViqXud36Cg>Rd zC#5F`wj%voL4*ehU^2mBukc72B(EDm22eqw4i5u-bkvs&!$5GO_Y&%Pw1L6nbkd2F z^i1O?;>h-`5o!D~2NMp3c#tWX3gp5h%xE*zBGOW;9%fXC zw5;I{%oNMb3RYSTB#6VUsuiWCNGvM( z{EVar8x{ckII(>Q;_YQPnA*+5AR`N<`^KvJUF3U@$R6#J1eqvU#F1r3;T$ znE~TK6tn}?9F~UIcel1uWeXU@EJ|#pv5|9CyBTj=QMz(sp^4i~Xt@eiXv=Y1oll`P z_@68NA03b5?MfKAyH>(7D=5_$*gLVim6>{RTv(-`HYZ!@VutSG-v#X*q)Q@eYs(Av z#KC~11W-{~+|Z@Efq6)Iu3h1qlq869<%ddPXr)go32TQ4`>JZhAwaRl$lB{#LgJ7? zAxNC}`n{rnYgfdzO-TVTPZHHGT@i;u_%}W;Yu_&$OXGjihsQ_%eIFg7 zz_{EuU>M{}Jt&R`{^+Pde%pi4Rt7%(EU821AvlF6H%^~n2IdaD)N;pnZ7*kw0R}vs zU)B(a(0F&k7$-9HA-K3%7;dl-__3;;DB_%FSM6;8K@P)Cpf~~C10BzUFR$me)Z75= zWJYd|=w)I*2-H-;m9T=m8_%<;U{pBy`?nIcK5VOseQhSwrrcl z3K*mj8Mb9_D-vo2vPXbghT}$>p^Gy1_Np`|t5%9RW=@)st&K>g3T0#ib$D;QVp}?O zAX+H3EiMV*b5V31--!PSo;&^(W6(JE732JqRXR7R+Ey61EuSV3B2vqm7;2KVgY=g4 ztfHMb(TsK&niwvZapou-9dv`F+P;+})n*jzXc7+Ucn~rl5{2(7WK*EL%+XDW*n_Cr z;!cy#LjC9+s%AMvHDb1MRsdSfB-)BAai=M+gUH4qcw6b#1;ao!22QgR(-=ueGLN8h zJS%2O!IC-6M4m0kGFTu{rkPYj7P;ZJZngo5MW*HKvM50edsP(6y2@?DNz}3Fc?DUu z#Iy<1qa>jPO}c~xx8ZZP72(wh7Bz#UfdMnRBNN3D1}vQf)X5lpy;3XYFMIf3b-ci5H+4r*f)}P zNVR#n+D@Xj47cGj!TCasqMy}KVb(_V&!pAov#G5x*VZYt^$6X@4!6VUar_;1eHSg7 zU0W1DXz=M`gCdvO`*^Os(`fHl)e5^%$qMsSvO-R!H*+=R;W_+A5P4MYx-yLIV ze4@|j8}BpDpWrQw^%>{S+}LWj+f!4owpyd(d$m5}{7D>wvZ&&)-D;n4{!}$RE*$MM z&Z`*y5o?W-PswQ1sq_&Z^qJCrXOSbLqgojtVLPEOr#5LrPRC(|?L5>D0JfRqDtjK* zM3q=jQ?cenEDpR~7F8`rH=@(tTxJQ&t+pgW^1z-+J5+Vz0fJJhLmHt<$Fi+iKRNXU z(FqAHvu)X`@1Tp8mGN=RO0F+ieQY0j-6uF%~_iHkJT@`A{AVmqv~ zEd`OSx}*6(W^>wIbE2*}=%2&{rm7TC(Eyy{=1TIv93( zIk2{6S13%X#4Af7!YlCEc;G7qA6EHXEo4B?)+2|HQ##(Z!gSxC#RDT-apSXO|Q$uvo1UnEP)y!2=kdn#F3a=V@Ko!&~A9&bu`IA6CL zR!13lAPC}ioSV~75j*WEi3k6uyedkS!5f*}0AR|IaA;gO7q`8X%`s_ZavX(u<3m2% z319$ILIk=pHeA}q5hb#lF=ijMSIg{p3p+VS-$sIcGF9UV4%t79RVGtAc`4*+2tjX0 z7up>!aVv_wWFQ%C$Ln zI*qpC{dm0MG}A+NvKQ=S(=dZ5EetEoAV^{alB(cxwj@%4zM*cJhNVf75XQ)$un=Mh z$d{OVEu%lF{R@bSi|etP^WZz}%uHeevf|ckR$CYl_b%~0(6==HmSKG1i1D}~0~+WH zew9vOzi`BOrZl@gRjbvi@743%IEnTvW9f^~pbO;IH^U18S4It^Z^tnDzQr*5K4TcT zoBh&X<=-dYFpR;Yf6Xuk`#t!{z6mXf>+hr#RGnbYr^h{R!vYp!f23vmNOTP&4XvO%hQR&Oa1UMUoE_4~g0}2XG&f#LeaE8-X&>Vhpq_ zSqXSZ-mRBu5NpEdg4q=_xd);VR=S1JXS4+q38VUdX+V3CGe*cj6`->VKepvhcCGGc* zXup3{`~73M2`zB=aV;IU)n)omXz5?ket%W_{ZrcSuNej%kK*&QS|5K-yLW*w4YH44 zHw+qAe11V|_ZJNVUexsYC9Qrq+=CDB`4tTw+g0!cK5(ayy!7iD{J+%Te?vIw;{%rq z3IAIf{BLXUzoWtbt_F`A;}W0W*Wmv^ga20={44!vi*8RLUclQtXaJlj$aVTDJq!1o zc&vjynSKmK&Zs~o$1~|?k$wjL7{@bBJOSy6Yw^Xbr;$~cS+X`l>^-RMEQ+YsDL@DA z&JRA0^!G@3!U}io2cMwyOzXpF!aTxTS4F6aizxD)nIzP6Nk0bqRrk)!}|LJ1-O{D*PF?|8) ze^jjhMWn+>G`Ntde-Y`Iitx)wpGNv(2L5}HZWH`-IwO4^=?v-La}2=`#xkY87rE~% zw(@;Q$G{DKZwCJRk$wT`-}S>7PUT4`dkQi(rh01n*_Dei&Jgh^#MW zN_`1ge@A5XWwL$*S*wE6zLd%OQDl8il=>1vR3h{YG0Bf1>+g!JA0_%sWXk?H0REt~ z?3a=CuSC|5Q`zxM*`ELaqDK%}GFe|i78Dy~{X{0~tH}CR(UEMapF-B(6IoxyOD3u# zUjv=DP}}Em^mb%yR5Ah0+n+@?9x)vJ8fOAreM4c&{W;`rtK9y1pMnBp2KeUz^9I2n zf~RWu>x7f&$&ZP)C5@@}UjW3n35c)r=AYM_|3v_NyAE*N^}|k*AqR6cvPk?(9f@D(NZ{cGH4ML@ zBS8Qsf=-er#Bb_2{CWn5-$K^^C}{NMva$GWK>TX~@mnQ0{0;#APzMkmeHl9ZE};I6 zgv#LXdqo^_gYo-14!>7|1E!n8fdEc8apGH995C|~4!;ML(|WTLsmr6-f8c}fL4F^Z bVt)y>wc|UPjSyF6$x5?TA+JJF-uQn3M?OK- literal 0 HcmV?d00001 diff --git a/MikroNUC/20260302/20260302152002-Config.rsc b/MikroNUC/20260302/20260302152002-Config.rsc new file mode 100644 index 0000000..87ea933 --- /dev/null +++ b/MikroNUC/20260302/20260302152002-Config.rsc @@ -0,0 +1,2748 @@ +# 2026-03-02 15:20:02 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260302/20260302154001-Binary.backup b/MikroNUC/20260302/20260302154001-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..90568354e77ffb8d2cb93f50e14836574bd88d0e GIT binary patch literal 307416 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 Om1d(vUWKwe`+orvNp-gX literal 0 HcmV?d00001 diff --git a/MikroNUC/20260224/20260224122638-Config.rsc b/MikroNUC/20260224/20260224122638-Config.rsc new file mode 100644 index 0000000..6f7957b --- /dev/null +++ b/MikroNUC/20260224/20260224122638-Config.rsc @@ -0,0 +1,2747 @@ +# 2026-02-24 12:26:37 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-download=yes crl-store=system crl-use=yes +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=AM-Setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/20260224/20260224192006-Binary.backup b/MikroNUC/20260224/20260224192006-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..84912c14db0282f2f3e017a53be894d8ed40d7b8 GIT binary patch literal 302860 zcmeEv2UrtJ*Zy;^2 zrz=&d%>V!c00wA3)LMCiT6qUDFCs7i2FCayV*~)Ha*bD}T4Aqi$y;}=s;;iK)aAPX zfH#N;D!?)fj6p=u0O$Zf!2mELsKSh)3NWZ*fB{s|tE;Q48BpZ}7Et9xOA#wmEyY+Zc#!%&9SL-I~ z#z-bth%=Hkweu#r(aGeQN~t_OO4oRbu5k(ge9`3*|Jopi0zmUx_cs8*CS940waRP* zfWx}`-30b@WLlo$f$L`hcB0rT(?5r|zf!02caA5(#W z+0lT3+0uXk_B3D^G@t>!6$U_~0n1R^%_C|}_DikKD5x`x0vKK8OaoKE=%1^rt82P6 zlxq^@YL*3HPF7N$Of2N`xlBG!C}DCqVgU}AlcfT0&F8k}%38DJt+|TU0uH0jyNL3k zBEpmg`2ZDEz<>r|21p#L;0+b94^&{lN0d~e#1qkl#(2#Dv}61_JaV-9Fm^+vGoUlK>#oq0CJJMBeBl~ zG<0%)3;-DBbO45p41hsN0ALteAg#1U_mYs(C8MvYsNN8OzUYn`6-`Hp27n>U0H7Dj z0WtyTv!ww20O;p%fGhy|Ln=Tv0G(^9?%BM`KxO%y3LX>@ z@l<yYr?nv!Gzn& zRMI55nwg~*XEQUC<>~26Bm#9xKoc}YtE_Ac|2Gn#wdX&TfK^sD2BZXN%jx{SL?P2V zNaRFmI^Tn?G!PNU=S$M%>P)={{k{OYFHI4rDiva>T&hSw?jHF&tHEb2TzK-&bevr4(Z^Vf`~vh^)?fgK$w6*CI5}Qyev_g<|R#5%2PG*sx*yKm70#g zOGR~cb&#&Vx7F3vzPkK7(tBw?`vD+GM+X`Y232%a4|U*80dTUyvlNPE?*1Xc0bQcv zJ46R}@TkEZX4*cLvUpjBQs(yPnRzP0M6IG zG30Ty6M=kDY83<3q!%Jm5aPlBoM>vfSjMfZ4h7YDuB&5FyN*FWwNfKz)m4d#DpggJ z9WiS4qR2>2=4mUC6xUEjLlv$`Nl#06o?WYsp+qcA%1A@VF=c(?!mkfu*6O58?oeU~^E*$#Pk|My*Up zkgL-Z zg6@+r8IT?u1E4N2gk!A$5U)tzZiGmn1JKdTm?6EXr&BL;^dC#)+Yyui86ij8VU(hx$wO7^>wdDvf;Jw=)Jh83HRHEy4d#hG^eXM5}|MdYNLG zD&2=nJ=GaMNR)v*MXXFlDulE~osle0ugkjWEgjMmeIDtFKCicK6hNyA3?LsPbq(nW zU5CSIdeKL=&j~frj7Q2hsk09STxQ+SfYzHMKY`6`34l zI%GPtfUYu~jYU&w4rs}uGwNs=feZzMLare6&K5210IeT^g}T=KYBtSeMEp>MQI-UX0Lw8L?|52j#6-KV*7`aL4 z3k?9Ryksdl`-oOxXeFuwpx<>RS9%N|v>a=KR$`=&tH87_3th?h#)Y9ZhT8C}!6uas z*=%HX8M>=60DX%Isi5?*K(waN{@)CM-up2CGV1^qfXuo%GV5T6k_L!?qbP9zU>G+7 zpxfI6G)AR;08XLOrKn&TSsy5lh)u@;7;TTEI~D*Z(A5zMhPF;iRJ;{RB2b6APk60- zK&^a-T6zCkdB0kDQLTJPt$c8;e8*aO_gZksHz8Ufixh6YJo}Q)C zntK?N931t_FymA@GkunAPaCQ|_>V8Ae#hynev0l-@f81N1Q z2Js%{K43sEGa_Lt1N(^XRHEb)1`OlRm=;BU(Os)BVB}V#B$fgUVkbo_KD#JDpFaYF z-4vkbTLbK+XsbCOx6D1g{u8O0!GtY1GrMP<(i{%Gyper1)#W7wUiBS&RjMi@UC-a1e>;B-{(1cUHwmwKqDqsVrm8UvlD~tuSS?RRN51u+ z$6kYfkN8@pN&7N0(vnqTnO=Hje+P#twKQ0e>;m2!2aj4*zn)O;zlVM$r`1WwakAxS|j(> z|9QOrZiQj|FIr)k>2Mk|Jw=>M#-!3zYE68yN}8nK<;c-3gV91#pRXeGBEpe8)ZhRj zq6u0xH$@2@z{wb$8}QO-vLkVHiUI{hP$)_pfj2}s6uqU8K?yQggI4rp^fT9$+)r@= zXS6JDgc28&pyd#XQaBl<%hgJ8GM@8G-LrnFd&*z#o`r(mYOyR+=0)xb>7!L~I%c73 z9Eb>gAWk2^HUl!ALB>eBQOIC6gNhhZ6V65}4AYbGEGu-UCa8s$@r)yAEw4^X zN3*1j#%VujPYQK{J}CBN2HF!7s5Yhcm*$9MEiakLssv?Czzs#C&<9HvGDhlh9ai1(*Tn`vz_zn@{gu)h1bcIr#f=n@rXJn+y)%s9sfv#7? z9DN>@nV`FmVjlYKhxQayMnqTuEYoi5H3A?9O>WGP^JAjh$w6~L@c^LjabrM>nu$Sy zM(xI(69CJpU&*9Ej~$;+l;^tJI=9G4=vi?3i>>D&hr+UJJsz=3w_}a~EQ^SS!7tXn zwqCM4bjlI_m_bfRz752(6lLmPr{-uRt%e%3BT}0hig@twLW}ycgM0AwBl7ylYDY!hha|h@4CHGAC9-CSA*80Ya z@mk(w#Wj7>w&N4Kwxx>-c3){`im0KBlu2q;muP>q+wf%xW>1>)xf2ZLBl*^lq(TI zj1)vryhNOYLPSXXyu@O$K5nevlSEgvJ!qhh)RRI<-UJb0OUC|@=Aa{G4Qe#M3Uk$|84_bU5@WRU zN1EubW=5-ET0>*4JDc-$%M4jYioH%TQJ@v61_MP|b><#LRVmHTS8^<*u_kS|6H?J8 zHM1rP_P0cL>Y>C8B`6M$M8^sF2Pec2C&ZYVs24dw$XKBLE*UdDMZ!cJ)|=Y8?38{l zeStY>{R-K}d~tm1O(NOP787uyd8K7Y&_OzCT80E|U#4fLYvd_t+a7&9bypNTMP3noPy|&k zGNEJ{5uvk>x=^=0VlRq!Ba`lA7LcJHqCMK^WYQ(2lQcloQqave3`wjpPyr(kLJilS2JEX!_tIqb z?X9cL*Im(Q^m$}&^?Br@^m$}^^?77_^?Af2Le~!3d(r3DV5kf_NCC(LkcTLcw;%-= zp$)Vdt=;rN`#}t>9{P$VLthPT5q(n)ZNPkAjZ#w$)Aja4HA)@T&|b5)H_FedQNOK5 zAst#xHR{i*(dwv1tEoo&Sv7+?su|Q&Ga$5_{9$Z{-&RBFrX7~y&uSR`tcDSqRT4?) z57_F34T*$4j|%DYs2q~irT}#2&=jRUZ_;aeP5$1;IZ7ltQn@;1wr*>~6*Z#6J(0R2 z2}smtA~6N+ZqH=heRRpv06xmiQd?y-^+Q|2AG}+7LLCc@ViAcQ(bmXb};9*wq@dP8ssy5iZ&L+ zZQeq`8^qmTIB@ulUDrPB=Pq0J@x;;PyKkL;$s1veB>;SLLn8)xDp&ExO_GX$9Yn* zn8Oyc2$q;2WCFR6kK+oCLL!tZ1YAOa6JkCt5R17oE|13>4Zx~Xq{pBxvH+YM#T=aA zNyLO)!ISc(1TN#?9KM_@=W)e6AzOg=MMzF(@Koqr8L}72=%iJ2WF$jtBxyP$Sr09EBR8X=?B2IQBJMj1Y1&g{j zG5}fB+>%&L0^nUQH` zvub_)caV^WIoBRIW&qSY%pCAM%$SmgVQ{<6ElYLzvPEZ$x~>RYINqdR;n9VQpIe=p z+5=-ap1>w8?SgNPeD8li30>#h9_M_0q@fQCVVpYUFm(5glWqD2-oBtXY_LAl&362N zxlN`FdcL`15&g=Awf#+nhVq=A?bN7pyoc>ueVuvTD_H-dS@9whaVfU0f zX}kMb?EZ|s8-96N2a9gR@(la)rx)%Dy6x7dVkY}TFunJfbMYHm58J(9MW>KK?Mg%A zlQZMycjix+d(HWN$|;+M1$~ZJom_7tvpd|wV=l4#_4CTJCVuBuZuTXvn4Wv_VaWOI zn8X zTybL!?QM28y{MV}=guvM?O|>`f4Hh*Z_{qax1`MOuX!-tW2NQBJ8AP5oD9jIF=_0C zwA(Aq8||93yjptxu2Ju^MZ4$pV7xkCa3`{&Kw8;;>D3L28xqBZ)2Y7WUNbj7?$>GF zoNl*U#_sWPdB$|l3uu=eHL>~ho4FmA@n5{Wklow1eAUBxCsS8-uoHL%U%3^~uEkbf zWNGU#!}p#K4|EMq7CYIWr>)Lv+p2YL($Xhu>)SlKG-~fwLGtYh$)l@fTl=|o#rHTg zE4p><(T$*i8#gqg8{kiwJ56>6><-(y{LPc;nAPed`G=-+;>Q`cJ@n}Olqo6Y$af+G zQR6%JMxyiFr0@K#&|35SolW_z(7zS>pR3Sc5fO*Y5r}cQki+3f`2wkg;BnRhE!Apsr>7akcut_*z+T*qR-bZRciq&FFk6}8kis=DkL%@(l@fBFTv#z zIDz~7vY4zokk$zro<}=^=TVDwNXzu?PQ#Wll#2da!dkhUc&VuE=}i6&NGpgS7r`u? zty=?YkrvJ-g!)Br>@R^mHqO!_x)yrg=&f%M;TRPX=@=2|>!@XrBjS*wzc1@g4f2Wi z7Lw2<+oh^!g%L3aQ``phw~874s^a5?2e-!WoU-zDZ{PZ9SFNDZ&3I#1L61S}!YB2e zQm>Ei z(7SSIPLOhe7GdRKd3YW+7`Lif(bI8546CMKP-{`I8J@dGarg$mymY4re+9Miu4gCh zz5!NUoTD7=r`*4jdf&XVa;w!dL%Z?9ACMavBygqK;x>l#mWG&tfe{s}$x-l3eICPT zeeguQnf^PDjj&JDXwq7Hd8wr7Y2Pe{aG#n|lo1?VDXAE(mD0Z{_?=pz^-2(dvm#gbi_t{Nv2@9k)c7t5K|1p z>4t_VL;0Gc)ZC+fr_scyK8HDSu##PcNgp3)B{u zz`8Uf{pt!ncbUf!+WP*QvJC7jca*tpH#$7bTMnzVv1|X zu>}+EpWD1@q-OoAl%g3|Kc3$?%x9j_bOb?>L9KzHeI#VG9ffaxTRMXK+tU5EbY8zL z-Tw!c?khHz3UGp}5GtfRu0p1e3b_)tR4kB6`2rqaA{284d1`Zwp6OXc|3&8 z{{r&*88V-&3w9dnf}ISA^!8ON`>RsLrV!#CDOG7S=`wM$+zdj!gH#>FGFdi?chVp@ zRqELiMLmO5j^u4!xKpmyC>2VnSR;4z&Cn#O)JjdZBlFiVyKHtRa%0KvVNPw#PDhwM z*}cxaB@_m&1F*LWQZY%Ym0ozisGUN@jS|EEn3ImI~0Hq8Tu_a z)@?D-t&MbCV_D;t2p1b!8-HaUt08WWZW>!#*5Y9+6g2f@v2ZUfkaqu7PLi=wAuhyq z!BP|}<+BJjOON3H8C3pR^ksKn3H?=NEa$z$QTw9zxxw8YIS;j7a?sHqYcuTC{o%p$ z+#bIh=FnyShO24Q4-;64K|7-^&nqfJy<&0a2P+%IB;C$6`uxT=BUczc;NC~>CQX;+ z`T**L=CkV> z_1++;q>Mdv_IjXExpBKEy#^i`_^G&MxM7DOV_PlvpXzdBRqG)$>vfGxD@pQPv-<3m&alI}R z#k-vbzNwCTCtooy|4v9rs5;|nuk7<5r^O~v#jggpF=S;h7dRG#%13T^zhw4~OOL$D zu6BQ3su`QULEv}AV891T#+EOOOD?W?cd^|1c%;SP(SfI@Rc`idX}Pkn*e&-^>Op3YsFXf>nj zq48F&8H;vy_+nU}zjxMMqUf36;U(FdR)cLmQy$MdS#6YPch$L2!0bQnbkr;5op|=K z{@w$O?;OjC7v8&_vF%`{J^NIvmtG;O-nyR5jRc%c{6{ z=WN&cGfYMAmL_eOF-(4}fBx;;9d`A6|G3dxa;MSmA$ca0+-a1}Mo*-YQ1!Q(|DDF@ zx0?S}^Z%Hdf5mAWE{lUp*aU|!mk6a&fs`xZC~z5H!e!$^mV%E0T)03e=gGNZ9$QZE zIYOC?EtZOfETKRy6O%ZtF6&yet4zVkedAwt(+G3@=#&0^TAKCE z26R}61B7}w(;Xu{eLbDfZZv{787YomQI1lT`W1aOLMTmF zBubr;u93?eyT~>DRO+N(+MOO{SKSf8vQez7X|-V)1HrPkO@0c?zTcg0s-=Ocqk*ZT zf$8u29SqxzVAys%k5Z(CVN_a&J+*xt+L0by3x|b;u$*y6txaq2Q%8G{O)#Ugb+b6-Piv(eSc<^?|d3mq~5mg|xxV}1@c5OBh$Z5Yn^Mh3oWUv6K3r6GU0^Tl)kl_n2#a0Smeolx z@C@xtXZMGW@okJ2o)D#9eX}O?aLoDcOQ(*ie6up~oXdzds& zrk6PCw;Oy)S=j!k<(5plUQM@zosMg;R9SAsc0U$2<>S(*<545R0+xRa{sZv!6>QNn zPaZd_Zuair$!FUOcibMv56pP~12(H;t9r?@)y}6d?ArNhZjvW0dtPqJ&-U%%ysmhrZ_g!ZH_w&zJMMB8ZYIZg-BOyF zU0$)*!^O+0r|`>GRNY?xb_O$G*ywwHjEfqI*ZWbIW<1*Ab}ne#HnYG+{Yq^X zHQKs}bzru;hRUgCH)y{2k(p+5yJ?3qAG%E~Qe3~a=CyB+W7A`Xrl;K<(eMn*cbnHP zrgisBRhNfdhSY1{gX%orYL}v$WvAoR0~=bjU{1BWDU90D@oc8soS96+B}bnM&#b&U zZ>EVGh3iq`Gv&d@hqI&e8w6h1%y~QblyK%{!K?81p{)@3Le@ebCqx!R559gY_a7ST zUot+wmHW4H|HqX3E9BxzxdIMPAmefsT!EY;F>LZo*Wc|XTaa&@{q+YCaywK+$Br6$`BLcOCB<&M#j0TEFV(UDPlNac>u z7I_yzEpitWX}mTj_6;uk^G)pB28zyPKLK0kHTES1|6Ft|e3`=zSv@Y5S=;%U8UQ{d zzZNWuj?@Rk=+?$x8OgFCH#TWT)+V+1$!dZ((jvI}b+VP^iMK-kr&_z#jO34)ivSu6 z$BEi8G6BwF32I_w{~S{DC_kP%q@Z($6k|#r1%q5GxgD?G{;Tx$WvjZHWj;IUb~a>n z*iiB96^r|1k%HgkFbeqzk^*hIC*xp?Hv1^;RW0!OBF}d30IvICFf>kQTK$ket6>LwHiweRK7xkKUVGZF(1V{m28W)}l2bqc``QxnZ-T_puyj&YHn(5*1j72UwTD z$XV>(?D4-!+w-dL zMXM{zgH3K+${o#^Bq`XaD0R(0Ic!Tw`$a|=CuX1U_gx%a|4I}tcaJPmz6M6T;C)Rt@d{85i-HxMA{hOEV_Ko*h z-l0Rqj0asu&JAnYHELPAFB+*=Ntm2*znh<@f5VUsFI|ITD``z8oogQ0DQw8P@?BY* zKPS|`b+qfSCg#!$k0jeJ#7BER?s>?aPIDD*sn>G(>yT-UjM|$;ynXhjdcoLSP(6l z@J3nx(vJK)2UeJTd9mzK=jaxOjw#Vu9u1zy<2^e!vy858HZwJ@Ma$F%BfZ#V1mx!cp16#-Sw z>z{ZPoVgqzHrP8&wJcLTe#}_j+TCUbr}~b&zeLqEc}ZW%!AoUB)uyi!EJvBnwhmEq zZtOVU_r{98*Kci29^2Ncm;B1ku2!4;ldA8PixigOr8Cw%wcGTt?}V}C!By9}eHYeu zo7|{We5d(#RZ)VgQ?L8i8=H70I<(1K`*di+@N?6{H6>eTg4a+Wi1Y^A(^J8kAh z?v?!s#Unc{cc1H0P~Fol=~i**8>8poc`kP3@d)23k1K*MK9~7M4;&XunQ~n+XW!Q6 z-Q6|A7SGyTc-YkF#@kUm4ROJJZ*j57&DkOQ8(sK(N4YU5aERB!yp?CA9nubrt7fvd ztsXyMV_N>2b`45>+%J7TQn4Cl8I_q!czn$Plop5OT5p@O#leHt&dFCXM>`%3ch zSmClSWT5m+bxoiY`5Zk~|84*OEw1Xf{r_$Mf7}1x_WwU(|GzHhyOZq|fc$~kM7a^F4T_4DUu8|%;9GPMViwWl0{ z*x#++{3&=Ir9Ga99n`Jg45DLpypCJMzk`IIJhFRz>E-RCx0rk~$#FXKa@Vf(H|$;wcW@q;ADXqJY|6WrC(2B= ziFU+uW)!f` zCmXkAZrHVD=YtnMJACbQaE=|e<;aNfUB>3OTsCw0=!2(W=ZC1)cA94?>u`7!<9PHDvvzV|KUD{_b@=kD_x+bsV!B|7{%c7mwMw;x5`4VxtqUp?Kpcwa6iH$=F8TnW3M|`s;{|;r#*kyec02~23tq9x;CuG zdCjM!_=BSsTSSZsjIP*{(dd58-KaI4KSZm$QW|`)>l^!|iMx^J;GB-Tk~dT=Dt;s5 zXHVSoG%zmbR!U@uWbMhOCerP#=Y0B{4b#P%(&l+S(l_hWeHxg}ICidH#tHtXF{Adz zzLMm`uaB4GAC_(wWp;0p8OPc4aB9qq(d%F4EIPUK8o?Skq4Z|F<%gsd!97pUn0$KS z9cd3n=EfMwtO|Mt)e);G9Pn#CL`WjXHAx!r3<97p1iKa_0<2eTg zB^F7REjYE(sE1qasG14+%s2*?v6Zf&RMq4eZDuyj8!kMTX)rnNmiwd>NiW8}`OD4~ zX9!+#`pmgIZ}f=f;rCmeKEzC&;@D{-_H@hWgaNGE37%u8P@8-D&*{W^S8t=~_RY8X zInLXlsNR5xPf6R`95|aD-sNOrMS@X-BW(lwn_+_vc6*R=e>iS8v)KWQo3!^gU+0`# zVO;IknE!0@Jz1=kV?V)JqMcw!#?~(!nLKjF_7~?>@F@ciA+9 zPCFjkyHg5xMrARa`kp;KsPSdn;^kuRGGlQ5e0acdhAhCOjn9zxg9Z|BryuK9FsQ}z z!q{}#N1i6mb-`POfoG1e{_+-|!p0N~S62Md@w?yZuRm1%uQXV{)&IBp|Hst-E2JZ& za+XwrOB6yGp%BVhI3X0W6%skY;2$~Pe%+U&(7_)9gg-x`x7R}S^JkE?KW2!2M3$bjrs|s~8O#vIvK4Dz z0E3kR(0S$A$}{Nau+Z;jrJ#qA$se92e>dwV&o*(I z_fMycdQ7ujeBA0)hZSdvj%|7og^%xl>I3J&K%e_FCZ6Rz^sK+NpTOhYwXqXS+E2ab znm6Cx*Lvak$0k8L-9|k%Jk)OFHWU9Poz_=u`LZ#pdu2?|^P?kn7tY=3&r#+*;WwBT z^JLR9o7XQ@GPs-Xg-!;2$kJr>Q*K(Xkx7m<<*6sDBb*(Gz zH|>~nzprY058rdW?H3Js&_TTEeigT}-HoT?M>iW%U4?D9`}AR>(E2+szTmzMTJLf@ zQZRk+KJ`*bUXz(^rIRx+-?MjNaE6^d78>rjIC_NF+vg2UUp_BAMD@5Go4n*0LGQHu z$(^cR%$xn))>+c~X#`z^HD%pN#(AuHibk9Gs4t>hbg8e1A|aJzN>R=qaH zrsqZp%@3Xq|M2LnM}z6XORl}LJk#vS)zLdHXL+x3xcIzka8>8lIqPk_%!41j_Fg}3 zRbjT1=uy>BU)PxMon4QP+10$_x=p(mNt&vRFWsu&?rc^b^I7Wj&g>OidhSW+>>-bi zm;|pEp3Q1y);p5&sp)=c;;W-ByUx;#VvjAmF>9o6xoGLIjUHCE&rVGGYFZe1*qiI<+Y3-)L>z!g`Hbnq3=utNnt>+2;MXD*a8B+-WaV)w6R# zy_a76=)Z5~%RW!yXAG`dy=~Txrk`%?Ha~s`zjyO}C2b6U(P;d`iBs468=V{Ib@=^s zt7&#UTgFWGjIm#lopiPrt-GlG&2bwSQNlcSrFVEkWu6`Usr#gJZyxzRe!WO_Z{(ce z@uv;z4>{@|ZV+avn0DN#@Q(SmVeMQBJU{MUUY7c_*<7!Bd-`rnhzJ>;{HT{y*kp=< zC%6Bo^V>QZ`<`AXEZdkh%{DX8taFD6nZ5~cHu4+shUTzE=U<-ib?MH!q|W?QP$UU; zEjuIIE?PY;#GqH;!yC+}R%h+Ml#Xyt)AU(oyRT@);ps*r7F{jAyxeSQWyZS`kIlX~ z9oyKzGflO3(*SJ1;W2X-A4qGdo<3lzbK0Rm33TjM@2y!_QFR2d;In`5)~h`j0{L5_ z=iS9uvNowa`&={`_`tig3jNxjDOw29@jUFMHave=T-AB^fhO@O~`xx zHqm8n#m%r4L5bbQKe$o+CGGLy6{oHCeKeV$SmJ5?+RtWz&$zC_gzGEvT1KUm(noq- zz8$s3;7WA?Ppo4so^|F? z(%=PKu9t?yFn#kXG!f%_i`TUuGx_SA?sJ-Kp0@bTRQM8KOQtL}M)vFU9NXH$cZEpD=RqUx8|Oq*(jGPg{OwyUtZ zbT%$K^-*}|isuoz7oL1K!Q>-LtIR{Od-4)NNwQsGIbM}(H}cf=fh#)=7DYFlzOy_F z)>ogLH?|kY?AEQ>qW9;oY;By8)z4$;pbYxz^f@KXK6s_5=2{rI4@`O6vt^j@{BW-? z!6o;LR&;N&a^35VTz2PcPX3Gfh8M4uteTPY^vdMzw-R93ElEUWLjR}s0gc=86G*LlHN8lELcld^M>kOO$nHS+g|PhhtpGHPf1^nn0`W9cJVsOTRVcx29k<(S`qZ zO&R|i>HbE#zme{5r2BsY>5@NsOR#Z;fWzU*6;h6zg^OhZzCb9G@K`(^hbzNTyhAEr z$qAku=Mn^mEfwPu9*->+%h__SoUPs3stZZg#6c|ZK*EpD<8xUoKZ5V?%OSV2eiAFV z@_hgUy&gyZOWzDSdi$xF{#7_XL^0~=qZlY=VTNKB^qSxL{z=TjMo-800gI(H%d^B? zrv-*{*1B!E)|pYsXOu0Z&s}`{#^Sc+9b5BVj=A~~DLs!gA6OB*aBf0Tpc(=MwU$__3|9~)?Ax_Z)naZc>1mn}TZ(nimv&KfW1o)i?xE@-wl z=u@}OmUL%_)+NNKU3&+ezuGg%XX?w>ip;=<1IA

    28=y#;=*d8ZLICn_(=B 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302194004-Binary.backup b/MikroMaster/20260302/20260302194004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..309752d49e4769b164fad19bfa779358dfe55d04 GIT binary patch literal 289700 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 Hp(<)l_U#}pI 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 A^Z)<= literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302194004-Config.rsc b/MikroMaster/20260302/20260302194004-Config.rsc new file mode 100644 index 0000000..f9dd01a --- /dev/null +++ b/MikroMaster/20260302/20260302194004-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 19:40:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302200004-Binary.backup b/MikroMaster/20260302/20260302200004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..9480429b29e1b29221b64837db16fdad7f913860 GIT binary patch literal 289700 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 z OFPjZ@VE*NpM|HLEnSH#cLKK;-tX7Iu2U5QU;rua_AQW3vd*CDOKHV$1;ZgPR? z&Py9}Oc>{NvDA0d099#3`{B3dLKQT@!ND;}i(8aGldKLa+%YWIq@#u;fMJNh3VJK5ds z1|2LZs=Fa#f?d#s<*ni_1X673XG*!Y=ON?lN6%VWuUoKu6Z_MotdC_c z{9f+A(EnhidIx2?WznA4n_+j9ano!byxeqa+xrh6nv>-`-cxVI)!QAC5u<+NQ+TMS z=l<@Gc1=~}akt7xO-=W+KX%_d(yyfm>WK9Z1hvN+xVmh@#g(k0|>E(k(}ignC&7ZJJ&5=&{@F zdP9%gIXvRf3de(|_SC)k;_WBvPWwycq7S@|eRdyN>vx~K5)FIi#*KJIGp&Mhog?Bm zY~Jj@LOXhg4=iZge29QWAu&el6~n^K15 zb?u$5+;;Q~>r&=k>)X?*Z*RD+-J5xO_<_e}eE^0Q>=Uilj%oU?WAxL7)?C|n>|q}(`VIEpy)|8W(R5v*ZyijMn*_jXOsz1g&SkYx|o#~B|EK1gWNZ^@(Mt2V5vw!p<1vt1YZ4_}*~ z^+Hm=;%%z$(r3pmzqs#FnANP+=Dq65!vkl{e_zn^^|~heUKii1mz{HDGV|~(o7Hc- zuO3d{&T(%Zrn4V2_{HtC~{OHgR~(V!AA zSyPp)flP&3q&>Ta2Kt9~?H&S!9@P@LGEoB$g*vV_`iH{NhOFgS#enlhsESNxu|NnV zE7e3Sq0uC$RSIP+VSx9QzAGG|XtXT}Z*_HbH7H)7FjW0DM^%)@y5g`IVOS+M_gA zD3t30J7?HIiC+dulyGHCT{u$*cIL1H;=zXroe@-0W{EH^4<{Fk>0kZ?N}9+Cg(NXn zOV)ISikO=CxP+Pl!0Yt{f#Z4<#I{E$pGww1ChIvvF=S|@T9bsLqMa-UvIZs#1+gum z+_9r03rN>M*X~BvGKN`BSHAdj!D!Z3b#nndCn1Jm9Enhdap5cVe5ruVS8(NgT)+`< z`8)v>cy^`+cOe;~y>}dxiVp4qI2tD;N@JBWC=LqfxXV;=af$Itt&$+Q1h!Z`W^jx} zLF@)3+*T-v4P|m!j*c*lz%S%*1D652vQQO_@fZImYdqJ~Nd=OVv$=i*j6Q=yk{B2t zN*zPxVXz4dRf)keFtj_7ZCwFt6I4Y$l@7Nh%V|SdV+IsrrMms-8Y)~v7LFw$Pu3>L z6gAdKiXL+~rs(j^qaYh(_}WG7Z%CPt<%W$Bnnj9i7KIdE3RxF>sICY!a2r{d8R`#{ z;sE^r004XdJZSU1`$DN!sah$IA`(<;ZA~fUrFzhSF!}m65XR63^R`n5t9)?MNHJ6ikR9+Dq@VJA|#B!RQ<|0$Qj+X1MAoRZ#Ab@1>DH`r( zru+8{bKUXqIDml^Qe#xjq?w>-DY$T(8G0VnMku&N`Mb1WKJ!}@L*0-!twV~iVLa4f$<>(mFiW0;IqEkttXHpS4 zC654krBHP$%TZS=no?^BNHt~{2JkGWrnEm}pqZXh?+ldsniM3FhQJ`C z!ZJ9znejWq%my_NLSY8> zjVdW2-cv)UlL)oJzmV!RIvk}ahjdmh>Xq4PgqU7u z;LJHN>(0aO2ttgNbcCR`yBR#mUH2sX6lkfcjHM})M!~!xPm~j$8bS+Y=WA?V2p+%& z$L2baktwPoCE~X7!zr+Bvi&YZw;N<<5#|D!gyoKl~lSC>tnna?;KQS19a0KE* z?2H0bFL_*|ez+n4s2k-;*&=|(`yVn5^#Im&sU-3W| zd1vxPJd}lk*w^$ta1J4K0U;P|k{4DQA#@BzS;rHk3kz&PJqd7~LWt=Ij6pdIKY=IE zW!RO#?z)b1s!QQV8SJjWJaq=l@z36%2;=fOJdDd00fE)3L|_t6g)&yF~*|UX+)fsNf(N+F&wyp&&M}A?SLRqhmGc zpMX)%Ft}2rnxyLf4c$qXkF?po=*vK4-&E+E3VmVnW3U*AO7>-tF3{(`EIp7w8bSkp z9dOMUJ(LgtF|+}lO#S(36gVHm_8`qNOBBS8()(02a3NTgG=x6T5c)_%=o1a0DjGu7 zfHGa@uTbd-(dY=#=?EFobprT|_W!Z>CGc%j$N#gE53OV8zJWxJfg}(+wqrX^2uE%w z#7;sI!qNUfme#h2ED1@D6ADeZuTltwLMWj?q2WGTTId1ghW=Zil%p4=7i~F0N}flV=ddNB&+Vw`KX#t_|o#M^zsgp~zsoB@LEIo!=h+CH;L$L-saj68%u)h+RCo`Q_uB8KO98#;2@%h1`+*e5YdkZ5zJMl zaK`C_40C6}Ucw~!mwXU^jvM$;PA?E)Y*Ah!QeGxfULnFTgW-gJON7yeFn~QzM6VHH ztby%JTNF}WC!#+Q!K!8x?n8*^uS9gULbO#Ox<(=TmO^x`!Uj4hKKiyoa7NJc#Y8tM zL@yQ-eMcd>Ng=vfffT|2(nH@>h_)+COz2ic=k(hYqB|6#I~Ah46r#HoqI(pgdljPl z6jJV2h`y%~-L4Qlpb-5~A$m|DdPpJqkwWxih3E$g(XWb$9#)7RQHXw~5Iw38J)w~D zm_qbIG10G!3Hq6^B=eL)^t3|sj+bbMm*`zD(Pkog&r7ttfP6!VJhfn?8MxHpQjbdm zzw$fmMI zArfR0zS+EFQ;#V@Ca` z%cGZ(!~zeo=DsbHHjyA(RmrT)vsHiiCEV3$Jg!8ZLl*MG1-?QB!n zdazrqwyB{1cEui5411L8zdkmpoyfrsh5myL3jJs3JSTh97>c>X!6apK;@s3(%Uf3%lL}XC!QGT}2A&P{F)Wl*<9MOEG6; z^F=O~N`J{EpED{s&KF^yn)5~2rI<5XZBx7XB5YOBHq9_kRD^k=3N_eIlSChU4ff&) z&%*$TV~+DfSeo^3;o@$lh5 ztC#ziEuTMknZJ3-(Z?)bz2sRn-d~PMVC%ypt9f`L4rlW?)Em<1_`1T zWFZVe7E%#p-U3rJbuks}Q{8giC!BqpIRh=6q7$cIg%cuZE1atG*^o?k^2lb2uC%1{ zBvBAft6VZ+wFsx~ipfFj&N6kPE=0O!gtrg>`{+C7C*4i@j`?8(JG9^Qokh>N@xz#U z4mvIuKa5K|6h0USea9Bg>-E5e7xQzC`rt{o6)Ye8>YsJlf+1dR`eN|Mn_lvPMJPxCNn9!(r8!Ed^3aMJ6)Oqdf;ki z|DC*{dzl1gTbYoQ+2>aRA!qgyh!w2Qr39)gV56=WDA^MYL_vI*9my<8dFIEwoqmge z`WM9#{`p!W)f!9rn^v!0AqezhZ*#4v_mKDw|8>1*ze>1I_S~;RWYT`Z%7dx(n6IrL zXL)d~*h?EU;ck$&d{!Lnw4AyUGPbgRWXv!knVw^=7C{^^z4J!note~`D1)MC9%~wr zy7?%pu+P5{2?rw<+jr5S*+-4pE#|?vv@Yh^iIL&Rv@GPA;$*BH^q12FD#})zRL^dZ zrHm`;|M2Rj;XnB|=3Tl@%DUFhtjPh8D)>zh)&OY|r7KsdvTn_S+e(bINd&q(uyu%t z9>N|FzG>_Z4r8m*?HtAe{#_hKoYlP?Mw}J4hTwxZE919_&bpu92g$oRj9|9gIE)~| zTRDtiHRC>ZkKM!XBXrQfiR~s2@cY9B{38$=uNQ&sNHfZb07>J0M6un+e~V3K#yi-q z@?(A_G{YSSY^RLho~S7K!`p-Bo87G1e@FR@FE(>h&X@;7am=#w7_fIe`;K{kLXbk z%45)xf_RPv$FIf361?Lat-}Tl7Ll_HBS#6db=U~)Ze5WL9T-nWEl9-T{-#(|+ZcyA z8wjq`5=n#s46)pVS}%zwG#-0;hsRjvPushOox7Vj*Id8Iz`05$&UMSN;8q{?m~m{_ zHe|=Skc8dDy#@9vv#_7J_y54hC*hJ_@N>b(nONA2>dd@oP?Tn2%*G01>#7o6;7}d1 zaNmjIavo!5VK&FY%tUkY_B}t!=FO|QjgMGv5fEfiv_Uu~F&+NL# zht;C>>kNkEpba;gaS~Yv)_Xt4M!>ENteFgf-88rs+jFaLZ{k*H_~O;w;Z#bqnw}U= zjYk-4)l_%5vmJb$m0`cTk71=<7`usKefA8iet{TPw`w=I;?mFa-0E{Ytg7~0TJlBX z(m^SG*mcFL_wO4~_r!==V$Z9C_BviYKGwCmt5vg@smui6k6;1}+8FCfb+u})SoZFH zEW0OIc91>GmVSX)mKgzq+heizh!%*4ldjnHwteinC)l;ro?XknXzZ%Cx5qnDt~mA9 zeVn={IJL~4QwM+1IMv6DfT~t4s~ce7kh(`0b+A374*8-ns=6`d)?szez9Dr_45>rx zId$k4jZ=r{w(9zDNQ=2L0rt7B_6WZYwddDiUo?Il)SgTQQsJO0UVUKS*t#di)?xO% zI{b^qtE2R>wJWJ5g0W~yi@KX+?Q^*95w0C>&$T1IXk0ry+7SqL#%JW>aBU+aR`6Pd z6eDv6;#FCwByx!rA=%mpBP>X9#b5KUFHq==8R3;F5Meh)B#yKf zj8S`&VAybBQD=Iw0er~+b_zq37#qe%-^kg$GSKU@#I2+3xpnMb&aEZkU?kQRGRgY*WPEE%=#uQY|k=s+3aQEiJv8|9c$0EVHJu>=Eu;*a^ z-o(KcP6Ia~Z9Sl?OL-t9qvO|S=dHTvy2by7cb>K@qDn9~S5Br&tG zsx6s}R|zZ(mbN~yaQ!1+z`0ni9BZUu>F2Bmlk7RSV!${zonU3R?Hjjn8yK=I5D!;{ zS}VhG$@L}Qc0J-gvv0&TXJ?sqjtvn1R@m}yz6T7rOWd&sSU9I)cqo`VrA0Kh&peiB zXEQiv=vtpxMB~@yK-|}W_?$V#%w((9bTd48hdEXIj10sF*)p0{{Xs32*UG9HtB$W$k>v7O1lC2?sT^&z+hO^-exPyr5_!+h=_1pzS zW&AiXg?d=tJ9e1u+PN)g!QznC7K}yPoPGoR>^IBg-yl&PJI6F0Mcz5&xjTUu3EwAB zb8Q**;1pTb@;JR3rDz zQYZil8|aFpkiiaw!|_xD@5qrn(cY!}m`UV{yPX#Xx9;F@0TJ!sFcR>U^ONY2fbT7S zAN9J6!$`n)H;0jc?{N+z0UwSM!3W)gGm!B?L)^(>B;b3B!(crFM)3_8Y+=wsB0HnZ zNWk|F|1A>m-NWILNDjzhB;b3J!(dPxdx?*j6z|U?h%S|q=*l^8tVg9-j@Xov<7GKw zGh=c*B+)~HJS5Q*j@V@Bs=KET7N>KT(K&%9HECD#8()ND_zydyn%Zdq@^&nC?gd_y^Jx@3B)f zcj*94jAWklF`2u1LS{P6-f<8?ORhbO$)3b3DO|d6S&xh5+)U}TOqPuAOd?;ALUb11 zKAT8ADpOiBc1EUiCip_jStv#>PnN5X+3U5$vQbK(I-7f0&S2=1^bDhAB_Azk`vbwC z7Ek%LWGc`a2`4+W(6oexle$CGx}vEB(*A{@jtaxkcvp%UaIJyRN#XeVhTF~PJ)BhU z&H1EyAEmTJXE+*&zyyZ?A*UXM0fB!dXW~pz46Gh@kUZGMYj@Inx^$@7D6?iEBrps| z*9Riu&>j6&RE$q3E{b{uFDg4)ogIlf+bn89_M(n9i^@A;$^7OO>l=3TTUqrS$=94k z)N>X)?I!EtQ^*r+tsxE>Mu)Ik7T~0{<}G9%c$**3MtTgV!xu+7~@JTF`JjsRjLWo9-U?()v)^TC=oj_R@~CFYUrr zD<1E+;^G8ugA>e#RZU%}nB^_WUfw>6C=iMGQyqbnzcY{uc4$f7-0@f>9NhS9zt!Pa z#pyacG>B^)D4P;idgDYgD4jvsYf)piI#W8@dM&Xr)e(-i`?W|?^G9PTe=ydGzuOYA zPXDsGEl>AbP0$lo-D#RCsL>#^KT0#zq_{1X=nf=8xtj)e4ro2nHbALai842pu(tx9 z>bJroeKr~%sjFcLKnxiBl$qrm?53QPWyXoa+)5?=-QiS+zcmo@Clf(GOfBSHHtnwd zs|GTFqxj$B5^Yvvuvv{E{ZWljGR3OF4%;-$$NsAZM*E-eobC%z_VdQ}7JNW&hdi8CC2s zl=fn?w8Pz$wvRQ?v}DCQ{U)uj3Y8IH=P?cou5Rd&hI3-9T-%4Y1B5h!Zf^cm@< zs2Po)dk4O}BT?S8@iWRzc{7_oPxf1Z1@k9u0FSaUe@440ac&0CbNyC}j0VtXCb@zE z#MV;XR3&#SD5GPWxs_8J<63e9cgSw#QzH07Z{#rip#}_p=*|2-{Gm5+_}tt8H#mB#e&}AzM$fe_1>tBQ<@RUB zI&wIks_YCz+ans(EmY}QeEAWo^ePTxY4KtXV`=dl9LCb(_c)B@#1lD;<;3ea%+BiK zFqQ!~aadg9JJ1ihnPZoQB|dgKw9OKqf^)iXK3Bd=e81yMd|2uemiX8yE!HJIECXg* z;=}n{ID1Q2;$v>+?xAaKfX>6c3y9QB2o!K}^3j2Pmk3q;EU#=kT{0e7Te4b9ru@lpN=w2Q zQ-D7$!6sLkM{K6E5O~`Yec9qUBpz;dL}%khvIb6 zX{w0DWURm%5u<$Ss5BRlih#y}(2yC<5XotXdKc_}gL$|J+DKpJ--M zqbKf~%(5fdb8z+KBD0F%>QNBQ&0Rgp)e6y8g`{Zi46YvfjzT25dNRnYVmGlg+&efD zeK*J~i)ArnmGMeH<{`=dL@KQi`w)86;$?&-Gjb=N9(L9`3j$Ber?XVPR-DUVrIl~U1#IN$-#G%i)igrhYk}&BcrXL4wZj-$rQ1^>d;5J8`Veox>4;< z)5>>4^xmWqGsvE#5iQCJN^Q`wD_Z<5TBeaF(mHS#ZPe^*8ZNdy zO?1+NZ+oe)p$QSJY7QjU`5}kFSTw2yu~{PNPsRM&hG3*Cr0HSRrfq5w;(V0rAW*D? zX}f6kCU@Ho`(sV=GvRv8V5mCD>+YIdN`~q{`glgz?_AI4B=y{6Ruu%+*=S|HbEvs?1j}I!8xCO?MNk7OE+uR>(%U;+-}K$1 zdf9?5Hg*@Ro!e4#L@vKAFn?Rb!c}T>`gNh@*E4eZH8!)VtlT>7x}1JpZ25Klq8#dt zm=U&No{=AwZNtCkB{dzK zq@;tBhElJd%EU#45(Gw-=hbOXGjavcR9vze;II#vIiUwGeHDL}<6?T5$z}t>3K$v_ z%?(<76MZ-;Z5b8aVhAqO*M!ocO#|c>+iS!&SCNIdVuuX!hvXu%hGp50Qk!9&R?Q>( zRIWC>CHqKThP;ieD(AwboR(E)fiZ)_(eKq(n(J5cmc@CZ%4OwmJe zq1-YlH9?sAqRYuHR0P>5 zkd;YPZolN2kr0}U^=Pb1LxKOAn5)lm#4$pdVI069FxI!AKn1_xoZ zV@e1p7!yJY<{ao)doXLBR%|YU?-;*i^+)Gp#fk$!E-KORZ}pcDs`fsue3F#sCWJg2 zSASZu=|o(+DujY^l!TBCfmZ!kWeTA~-YmbFIBORL^z6^@G!q(RfCMzB5d1wUplq=2 zM}sv(q(nXkAn$PjRh52GktNa$Gi}1MvC-Y+l9{J=Q%V@T_K9L3_IkoQL{juk8|*Hy z&}zs+XBx(=8^aC;FAqADjJwMeeXZ6AK7@`m_N`?yiVXuWPvh9Nj?B|IRt)3VFpMpR zs*=f2g}0}_^`w0S#cql3?SD(v2Ql32s3g7FXOK2xXe6v;dU6*f(W+)GX_1frmkkHdt-_^P&-8p=^Y5E%y7>7 z#NFV{*^MC-X>X2_DUdLe)0HX5wB~|#8)-FHkzv$gl)CfYAZ96(>lBGQJvnE8{VdEd z#e~f{Mmps(!^~Me2YNSme{0MP(GnwfgKYNaq*C=To7Ha1HdaOSJj6NqT#XqeQ<6+T z*_M&O&i1R{pqc!cq@gS6&{nujv1mVgQz&lXF zWevE`XPVeYu=+!wxD!WtP$7Cqq5j+*$^?HPr-@_i1#IkY5U?*3`5w82`ggj>{5Q5H zDGbrH>t7wZ+QxV+O|In9cF}DB6J|9!&@V<;5vVY zfo?&|sV`9^Yd|%?W23?-p@n19CquX^gcO$8oz!9O;tDdqx~HZUfcD(GWs5 zFEk{P*&6*Sj>1Iq0aN(Wv2R6YTCbp=*#EnH#Qy90vY&NhE}L6+mu_^kuz}4jrt5Tf z>c;*S#&Pz-IDVfnvhA^bg)yzWpxh3yD7R#?!=DJn{oUbcYit8^tHNPZy!x0mt5z>u zkgK(7C;3;{NUet+A3^N@J}JFdp*|4+pLdlx-d;-g-`k}$iv^omWy(@I#v-MGWJ*hf zlh$B4cWzWWnY>U63GiSa9{Zmm{nzex+4P6zM5@|8n?NjX8aJAAkD0NCH=!Rb+5POr zvV1p)RMK>@CVuXcuC|niNu0|h(D0f0{*C; zf*~#KSK2B^LmaazM>ANJr#^Q%XqvjkY0RJpPc|;#A=BL)Jl({Z^ z*!gFDn}`%-e8)F3zT+Di-|?O2GUNn%G2R_{rgx)CO^5X4tWwQjfudMfD&DmVOCe8~ zx^kab-k_KU?k=CjU=2UV8!VuAeip)MLbJKn zg7b$teGGXtE!DJ29Lha9Yr_d`aaSOr?}o$*NeS}mtgyM{Z+Uf_0b z!pnZk%&`jsrzhnw^coX5W_dCVmo_%ttslb9G$abs#Bwu7EjuG28jB*wteDjnL3Mo& zTS%J6ej^(k*a7G2l<>ngkX^n6=?ftN^{Dha3rNA{Ks@fG)znN_0dK1{DDv? zp(T_4WlL7A_RscDm9lhR*8lQP8BSCgDEX%h^6zGK)2;lQC#npvqGdkgfkpYIM4fjBoQ4& zq|D{H-xm`pONr=cBC1BB%^D(g0@k>P5qTPT*7upn^xcTfw=Dnr2}Hi?E`|iM# zFpPAC=oI8$S%*Igh$6_9+ezg6hnFZy`D~;VXFo6E-^Kjf$G=tnjTH4DGlA3j$hqIpC^ZyWwEfS7ric$Nw95&>=! z;3-5y&w6qt%kDp!Xy~uDB7Hg0fxBQnJGIVMErGP<;Ms%OZ&4q@ zuh?e^yWd=kxQ-I)VX5Rj#`Y}VP$CcJe%`fnTPiGXsdx)9cZ|jG7R$5F$%lhl@)0D; zN9IqQXu!+xdk!Nz`5e|J#11?-n8P^mpo+st$7;ZkL*pHE-y!@R)TLcV&r-gZ^ZN^U zl74*9e4YHAjY#v(;nR@9ox`UiB|9(M8AS9lhwqty@;BFZkfLCoswkwW6&_N2u_Fqo zloZu_7%3_hky2jR9SKBhs!1syR@XSYv2AvJV0J_G>_E-z>NeH(u8)){Z3WG>_xR|7 zMphCWA%H628-0dvv=zQlZ+xT9_(qC*d?UR*zL8)b-(~!JF#kp_e%uG^;oJBRZUKxm z`1rMX4_{N}xZ=}G-H~0wO2tLF&l7!(K8E^58the|+fPW+9J^n`GFnpJ(biId) zDA*AQN2~dFO{t3606wVqAlr9Jq<1Fx=oW>FskxRd!hKY1Ai!s|iY4VSKB67Pq`X^9 z%EvxZ3RNPHkLY_oeIHvfMjaoTN}-`DzIznaN6I5U!Xcq*>92}OrI(6HEqS?E-(vAf zF{#5|EhcryZ;DA(ep^gx@9zNpx0rmd6chaqKlvDUPR3~)0bE*f3F1=V!?6lJ9aji< z-t>~Hl=w&u4f2s%Tk0eAn`8M4<9(!-?B^pjxj%k)04|r~N8iBZ3S6$lr4bKi`}89k z4#SV;_(=5}j@w7zG8dPtedHU`OSIKTJ|qG87H(dP%QheRHkT4zhd;iJ%k{Y20VH?& z$mie5HdU$KyK(zoTz=^zRe283^FC6GU(icTzw(jV`yy`t+DEGQC0t&{3$NhvDjxh6 zm*3&?dtCm2%WFP;eEuW<{u6Hg86^JVBXv`V6sBu5QhY}h5&ad9+ez`g=Og+X{`d!q z`cGWm#Gh~ZNS*LDpdGlpi_06h{2iB_xcm#3_i*_)F7M;=0WSZ+b+T{LNps_7#YkX8* zTG!aPsD5rk_1v23Mfc(Ei^Wt>wRXcjhs?lI)!|Lz*1Kc1CaH%~uz$vZ< zIN!bj4g;L}KXY_bT#Rl*`*(D!sm?OG4aMl@sb4%tNtwkMm`3Q%X{1=!1;qoyqpLj_vF2;$vK3u9$Zc+0c zQAE16FdC1?7LZyvrhrssT!F6mF`J|Pa2u+zr-E2!Y0m__{ehQM4^um1KTSoC8_6`n ze}1~{+*Kc-%}S7$Qg4ETg|;hjZaaS77jLvW+eWLmZM6E&W222?jmFwG7D z25+Sqwyo4)+e!_e$5tAhZl%#+E$_00En;gGxoNFB-deidVHLTVwyibu^VnKr(ycXy zwN}fT`Jx0CyJ@X@-dg&k)7n~%wyo9pd2Fq*>DC&1h#-MJv{EU?_~~aUY&uTn0ADgM z5e~I$mCNR~pvvzV36;FuSJy$LgmD@icMrsf`Lft@B}Qw^4dEhyJK(EC%%KZ+2LL#= za4H_o$s6J$Qb&e}R8KojQ6GwV!U)`32Nx53XUu1Ym{PdOlmuRdugsHzU#*MCcbP`C zp2&A?kf@u;_v>n+4czgyk;qqH$~6E^&h+5qOa&3Dy}iA?Z8*4wO(_NqMb1UmQu^QR zl-7nSTB;l^ReBU$1&Yv8zDR8^%a zS1xo&3CK)xBC|do1)0|}k@IXn{imsjMFs#+Ix=3*DEcg;-)cbV{EVB8L`2OR*MumB@Eb{m*X~TWW$$ zOO-U&`g?oWt7hw9dDX5ZQ0oy!t^KwB=J2{iY}Ja^PJs~@p#he8Ah$9XdLl7Y`>5tx zNFVGUxP+LOgjqXjpCX6{Ls*{>8CUVx&!mpo-n1>WIT5|XU zLU~U^c^B(8t5r%1*K4T`CZcCI*S_V24{QiE*B;c{qmD%n-7$Ze(@`e_!t2--d`LXKX9{_zwj zS)HPagHv>f=`-kc?-VU4^pWaw8 zjqm3%ZLT?{6|;FqeY@?bHXasQcO)2WYd?@XA+Z{c51wGfA0Mo!8!$q%7f^F;!Ddnl zH96prPxNL+uAE@+dEDx7;4OfmRNB3OdLMo zDC&b_5OCDDcbrxk2m*~!F)N}%6Hze`6+0n{iiogAuD3;^E235N_BesJ0ovos97cPb z%wh4+^eGC_3DjIWd<7Pk2d}_l4OYra+25Eql&m1tJ7@*LAK0T74#A%YXD=GIg34(q zE@dmIyZ~)QD@+R-lO_7H1v6a6HkgZ8^O=~7Wz5CA1+B4RItS# zwc@u%OBEv0ARJ3gZ;yv#(*w~!B-W0g1T-g_3?F=tWJ~uwY=T}$Iz{|6q@|)-sxqmi zQsHQO5`ceKHzuYts@2DkRXxM^B{90ti^E zAhZIkQh?Z@VqDm2FODXL&qp0uL{#prt!qc@MI_c<32sUvA`3wa(>Yf7{tXyyZNOLy zFkp1>O8$PCg8R+29+oafA!8j7(Fh151aqN8EGkFw!Z%@k9b{}@M{D$b9VN7V-D~?g z3T}Pf16C|xudkHK?qMy6_9&ws76u9D1j=8)M1rAItSi`284t8;j0fDX4@wHIbIWe%$L>flsbQGJkI*uRxWfnEb>I#^ zVHK%I^?3ZGDqcUS`pB2mf?bJlYGZ+)%1hFoA_U@eM}nbvAk`6UGs2QsvtSJB2tjCqJ@%(>cIz5Joumkjp(o=*nNmej|x^R2i0<4S5iw<*`b z9o3bANCa;rQOnk(mRJw+K#kxbeDFPv*V03zpmrfhFtQmy6cge2^h7wmPTPo|y5Rvd zLPAT%BI~up^kgcK3I|sxI@J?7RrGR*!)RLrhWvkt-v?_na~K6NVDzpbxhT?F{tg-t zv6uLuR>yM~;ZZ9%jK($YBTUM;k5H*K{2hc#8F+AL_;P-~oCs%PvJYZK4H%td;K2}S z+{f9A2F^nTx-*Gb_!~Y5HbW>JK8P`G<1k`P4H%=Fp(sU#_$3t~qlV)Qr7(gA!Ks^9 zDqw9SOz6gkS?!9ONFwc#)nCziF%v`btsyw zYLCU*BN~+Ku*D3l3`LXvB`em~`D@(JC}5+O*QDXejYjR4?COEx&}^a;ANdIzOnoK| zMW!(*nyjhnifXBBrg^9SdGukd;byrY^Z$A@XxruLxUS$bo(cI=$t8*#n z{wCrBOvI(}L`uR+Yg||S02ALKa(|a5G)wJWb@)hh(*zS~saeRP_CO-g&PEej?xuLG z!~G_vM!9%JdapD7X>o&&bxXO4Zme0b61@vdVRnU$6>gG=&7a1mbDk;9?pd(H#J0bQ zt+caU<`;LRV|6{y#5dl=SE93EWkPFbEhq5_%cH^#W^;rsnV@4k#Kd-}+!3XTSW;#_ zNt_*#9%>?;BO@K!iDj>p1@XqL{jA_aJ?cyo@hlnfeumvy6^z8XLT!;if@!s?V5}1@ zGHO0<7ZNZFV)5G@z%<0y)(DZOyAgCF$0DZHAZihBfbFFofiOC|L_L_;dp7s){PczBK zY@FHV@pycCQVS-ul!5tS-bDC*n3`)5)o}`uvQ7^tVAaL%eUIESN5LMXM{b$pVUzt5 zki=0$N1@gqj+z=^yQC1#p>O>F{X#~62vPaqnwbq%^)sq!t81%jX4RDl+i+9?9*m;; za2cfUppZTVcz}tMdK!;5I03e?zGi_52Pzm(#M;6U&6ubihiMd_5`CG&-}ew5r!?1& zVhk~YT_>?bwdWK2gDxbZi-_oABKjH;UBc$+q`=z8Om!W$4iQm`h`KP3?11}?1e4;6Z2ng9>O8;nIq z17b%)O|j{tFYk_aRpEc^+o;S%CbX-H%-^gXGdF7gH0E&Ln3Y;InAjLkg=5iOXx9d` zuwCO~bO4WQ@mR0}GK>#y8s924*Wy+w^9j^XU#}&S;aC(CUhuy0Dkk#=44;DmW8w`I z7)6x6fU&)EeWJ|}FJovDr@Zi!W0>+1qAp6f4-#G@sLo>QK|&K<2n>HFJmdwPfpFA1 zzO(ICiTde@SQosU)4N*R2IE06Ehd}svr5fCxRnKIr#t-Q3gJzmMv%Cos4 zb4(c$Z~*m89ixw`>}M#9@eI4W1oE+Dye&O8yK%E%8<~Ir_0XF1?$`{U0X`l|!-I%6 z8w(Jn0z8;#v*AM-BEWYk*z2lC0i6kVSFu8>myNrH3QZl!LtZBK_NWS!8qTdNQ)p^& zbM2(w9<`*;Zws7$TPXb&iy&rWr->`n<3lw-rj(NbeR%w*4iRE-P!@X}@Fw_BeHSSFcA+7YusIhjtvKFqd^tIcuU)y+q{i?NP<*ZNy~SiWUrM z-~>8!1zOz0aH6z40_^e)N4Kkif`>+a5e+h$Hqk!-bD}wR)J_ z&2yrM)Th6M%a=Wdf`z2QXQV&}CIX@L7W*N{`3&DdYOWo^Y$L;GK8OfM&@0#o370bT z7aT9gd31A!c~SKNm$_06_3!f)GyNc19?a;#=n_rEjq%CgT708POPQuEVT!hZNGW22 z0^6{us6@&TZgMfB2K$%0uqhbU1gt46iKy6g$qXo-a~q_R;m(t+Yaxc07T^2n;}Ez2 zdkf*2Z3`zly8{UgTQ&t5ZDVParYEs#0nBd19PeQ>Z#bT6sEh`ff#v3RXmtDzD=_WI zod|vavgzDb0TOHn#pfujfGEwiJH0Srjc_(U#Ja>s9{8&f-==f2uK=U3d=IY2BEG%i zBQN<7T#GFaLkh6@p%9mMy`*k@&&v}{mHyjHzL6I{sl4wc-{u`L`Vaq=IB*NT$$uf7 zFW5SFUaIT3m9wI&>t}9gSByzfPw)PnI4Garl2)(1vC zmD1VxwI$WW`M3v@Q0>-QD_MnA*d?QFj6RGz(Nw$=OBY&#t@NQe=kXRnn;S3|kqsF3 zgaL!ckK*q)DY(y;E}1fC#vYV;0qoc!3^FCGcNLGnXacVHXp><%LvAhX9!k;f3vqonL4oWfY(wFm^V#!oXpi^7KONNf|VNmVHJ0q$$ zRL_{acKI872VTYWtIeu z%NW9ZWtiOONiEg4cB=U{Uu{{ou%+)?y3DgSFxO-bGASF4KFGwSFO9UUncuetrRGaT zo$TDWDShyinXib;AyfOjH`siy^zcdZ*@0I6B?~5D;?NOGCF8Nw^zJ|;qJ=8k1BsBv zL=S9zJ!c(J!Qad7H`o4j5Ta);DJA-5`UnepnrD?jPH}%JQF$rRq*9`aQr+~0cAr{G zbWSPJxurzsl@gs_N{ZdtXh94mj}0=MHBSyAm7c)GQ0%N$j}M}9`WY^d;PNmoR*lN+ zMy?Q%2s-IH3PI4Mp>RSAx;C01k%kHm1Up0Z#q7#T7YW=7!zV6hHQoa*Ln3+MEKMT z_ZtLwrT{kz@GJqIEx?C)(*yb(;r`(Qe1rfWDZobw@LU0&C&2Rsc!2;f6yQYyyjXyn z1bB%6FBRaU1$dbNHw$o!052Ed6#~3cfR7R2RRX+PfY%7{u>!nSfR7X4;|2Hx0X|WH zza+q47U2IA;FAQnO@P}4xI=)$0(^=9uM^;i0Cx&-RDfdw92ekI1vnwVNdZm?aF+nD z7vOFI-XOpm1^6@p{)zyfF2H99@K*(RlK^iP;4=mIECD`SfX@-&a|QT30X|=VFA(4h z1^6NXzF2_2Ccu{n@Ye_{5=8wz5qWUz&{Y+9}4h;0{oBw|44v;EWkez;GYWc!vg$> z0RK#Y9~I!o1o&|QenNns6yT=>7|tA|$;0Ov0e)71e=flPPk?_Rz`qpW=LGn90e(S% ze#3h=K5_$2{;S%6;=;8z9sHv;@y0sfr;|6YLqAi%E)@E-;Ebpig90RLHl|02MD z72v-K@EZdBcL7FjKcoHsDZpwg6*$qw(7v0{pH3?-byF3GjOY{BHq%Uw}Ul z;Qt8lhXVYOFxLH7xc@(II%Mx-FCk|j`>5}vLj{MulMW{wE!^M#opfm7?03>O)#2|D z@&U4s=P?h`JhIRD$2`a%$UgHP^O!D&rNTQ`KITClLiV}zb&uI@SG=CabM2qfcz*R) z54Oa!&x?Qc&^I{z>%V&FQVzfLR}Y=X;XD53VGD`)-1#?;8BTcD-#l~;f9LMMrGGp6 z4G(SQ_s6{9q5C;J_6-lqzK74aH#}^S5})yJq-pK!3WN#Bqc*8^A z+c{g3ozwwcW&3N#+;v`+fW`K7*zK8v4H=cF=<-&j`6aEW_+$4>!lm?*J;~W zFAhv)pIPJ5@6R6Rr7QUT!^U|{9yr0De&_9j({O0Am%h#4*CwayyW)`aJH6A=FjacZ zeo-pZ_1)5#e&>c+X&6TTCXT=4==A+(SES)VtG(>NW_(Ildri4GVr}{z@BgLY^(Uv{ z%66|QBUSBQQ@*CRr`xK!-D~n~O}m%2@bZl5NaNWSPQ%xQ(>R|Cr+Mu1b?JA8N78Vk z00#y5U!Cc99*lZv6{q`9)JsN4`;Vet3h?_siF)ZI4u2F)|8_zw4Ie7NmkaO@;^}u@ z6X1tWP2YcAfUirW?>{WS<;nE@l>&Ue0RKdQzn4nC|DpgN+m*h5jsRaLz>f&<{}bSG z>(jqoAix_1_!9x%(4Bt&fQ@PRK>=R%mGu3`Pfx@3XQbi9o6>MZfZyDlzF&G~8eVu- z8a`QoqXK-r01rMp{r-3XK2dX;N_R3?~l4P4gXz$zj0amzVGrh z{Br^RP=Ig#X8N7$u1dq72=E`SP2WFmdm8@Jt!en(XVdTnzf8lYy^x0Acrgu+eK`#e zdm|0s|MxT;dpix^`|mV7{{1xkwgA8XLHd64hiUlykJDr01s{7^a1TCjf0}-$px0~0 z5ZrWVfvHorACZP1UzLVqn+i-kFK#L@$KI!>6`Eu0Gt&x9eRs(8LKEkO^V9IJrx%-a z8>`ds&68A9A5~tcnqykkg(`iAj~g>CRL${l)YGatR+o=1G4;Y5FO-1@r{1Tyd2#CU(JA7@(dtECV|8Yt0kK3@Uz<{KxUI3V&#h~OBN5g`n-#|5HEf0Pixt12Oy^t?+% z70*eC;F6UPRXpMj(U`Z7ln}w6D=;O_O5n&0>Ds7V#7Jy>* z8a&AYB6X6hmY(F1vA_o{VDU}zAg04bmre32QoZ27mJoSeBl1d!;Qf{ndEJ&sW^1_4 zWkfF7dXjgDR3iA@WkfF7dXjgdga}T18PQO;Rg<|99)B5;-z}m|Qi-r!AR{`;C8A=P zkFeGtAu4d&{X=9#Sg4Q?`P?F!C?mouhlFUTTSQ07h_FN=A@aLLv`I#U^%V)xQEm}E zEF;3=jD%>jOGFhGL|EAo5mo%qEuzQd5@A_LLiC7RL{G?wu%;v-dfY9dCuKxfkdhER z=@!vbvWQ?cOG5ONYeWxAvWBHF8IjG%Z!wRUzOHyqt{T?SBt%cUEzuukL|BBA5Iye} z(YrDttl&wAUU!S=Lm3g4|0F~^T_T$GH5n1s4n;(>zUET#A2meoek?qSh>jW(cQ-;F z^-sC`v1%zH`selT5X~F?H;Iq1~rB+0=$nR1_ng+|=k7ZsFQPW_T-M{n<84=cqMMO)_aM?y3-;xnwfmuY< zagAFXs4gM8&t{*!M0CMum%Vnu=pRUk5W*lMy2o8(UoiSX2@&ESWJEu7i|8Q<5rQXVL=U+` z^!1PB#zy3Yi0JG8bJ^IJUm$>J=_a^qMSd2+xraz2;KZ?ubs7N`%-R5z!q{movyaej~RL0)r$( zzj4XgcYG=%LR682=u?-7?tD~6gpec=(VdUFMbs+`E#jFZM7=Iezelc<=luwV5)nOe z-Tv;n|B?IUsv(j}LUfT_SoUDIr4in1tvNm%aAXAK#S_A@oc_^v8d=E75a*lr=5l)KZM&!h*tjCC892wvk|K&A?k8D zX1}mTMub2=5zz~4T#nhV&X&~?q69@mug-R9`n|eDHbxO*C?Q(n(ina9UD@l0_(TcO zyEbF?T#M^ibo3*r(LjK;gQD7SyeiSfRt#2aNtT(S&*B4C47Tn3@GcP%A|ee$STVqJ zU{RMulc_*^BES-P*rKYczi*w03IUZODm-_I>i#*8Nu@$Oricp9U835y^A{2-gma3h z@Z2S;iDmNOk7!U4)x@%~OhjC?)xQHF}KrE_=s`98QZc8=q z_wuA2p{ydRdB4BREvkh_%EJjFVMSC6kJQZ@7ZqH1yF3mckXAxr;ikeKEz*(sPNq7AoJjy-$|$tzAd7{bC;;jJa1yDSSmz+ z162cG#m94(sOGKw`8gsg1dofT@Z2S;2ao@)R4T-ti>UD2C8~*K^Q5*y=(>ms&t0Ng zJ!I~UVg(WTE~3J7m#7xZdwqWq6$0l)RCw+Z)wZ3VN)<%hy@(3WU7}ib*Pz$MQXy<# zM1|)rQEl6))`_SP^)I5rbJwUok+d^54alfIajTuT?R-pXE9^OtQ9b6ittOT&mMVxX z3nD5!cUi$%mqi~D+X_1#L{xb064kbyp9~XGVZ(%o3eR1lT0LZ5KtzT879uJ}(TJ;knBSTHQI=7$>4K+&M00 z6IK@!_SK1~3>T9NR8NNGnHRR@iKw0o?{qtxu)4jmt4~B_xV>GJ%Ied{ra%#u;nR14 z%DRGvJ%u7FV+G9xD(ey|wj_$Ej3rbTsMdb)#MeX_#EwQ06`s4~D{FuNHbjc3i~s=_ zrLsndU_YgZ%7_qgfoj`MmZQs5^w^FmqQY~R72LLSha}F}%_*bW;Z~ft?c5>R?br-z zLFL|VC#h7}ODdxx_oaGWLWQlUGOE{eKqXZWJ6SEL+*k1914S0aMpzlu#|OIZ!A~Uv z68mUnRG+#xAU~}TONDK?7E~3kOSPj+M1@_vGO8VA?ol<0sIUpxf~wIys=Gy0*h6eV zb+=1Yvo4EYBBH_;WDymfyF|5Z=f`tIRM^2RqQZ0cs5XnJumReFYO`xpI|@Zq*gq|! z+EM5l)u$3OVEeU<>Qnd3@TpWP?B2GZa$l+)NTO_xqS*W`quSwdUBMj(iKwu5+=A*L z*Qh?0Du}J;GOCZ=SMcLWVyUom-GYj3BXFT{W?dFXR!Fn0u<>0)h3Bp-xT8Ttg?;lP zs%<-WG`K`{=6U14BBH{!dl40$yF|5Z=OTS^TU{Wc!lr+*RCw+Z z)wZ3lOJh5728gKe+%>8lQmK$~Kt{F0eW^$iXJjmpQIT75_Lg7l7uyO64@6XW?z(~` zDKF$p5K(R0NjWI5!D6Y9Zb3%1W3cN|?U2THWNWaXayz!qx-7m$EESSHh^X+~b*Vm< z+6uWML{!^$er(rPcH!z*X{*02mI|pRL{xZ=QWdZ64yTOsXPmaYAwPwI0L#{8@z!Kj zsyp1-jzo%mP~l_~>*gsWEfvdzG#3U+EMVigjwroVvFO+ZtCmCq$Jn4N@sYGBgiIMC zx)Nj4ihxdCyV$Q|M6zA6fMUUrX9Jif4`0UWS{h#0m8^(kTr8;rR}j~S2EJo9=5|MJ;lLFnaYUt zAwYW(N2?;4dMaRtGyTZQfMQ!B2MG`!J5H~3$$Hjs2Gd9_NlgwVLjn^Z(l{cOBho`B zWIT%<@F4jK@I1c!%dB&K8)ID&+X~V$2QxzftiC8FL+W{x@@Mw5UB>Q-`I2*g0!!+7^jijSM%y`GeFtHgw@RN;SMY91X>~lU?yp zAf+Xd!xhyWssCNo84f05$yi$ojqwc&9T7jW<{0=f+V0=oRoRLp{Z*+%psg(&>LRn8Z;8yjiyN;sZq9K?WtGOi-(M?!Y1k1rmwC#)j&8soYk=*H{RP1d*o6 zAP8oizHWVEb&VssDlOEmt`jS*3Fn%6{-rX3v>p;C`Gm+ zRAn!MSeva54TZc_D9#~I>D*Ei3Mb={z{X%8h4YOo6Y;9fP@kqpS#fq%7EzxlBkP0a zeush~iI!Nf*@<{%FcwXAb!rKuf(=#5$Sd2mSZ5$t?yj~V$y(jh9g2)xUt*ERB_l~w z`o&?^Y2X>3j3k5UK|}o6MGmx)TTG-qwLQ{W1^T+=2Lq`*WPfa?3OJ2|$ZUp^9LhOr zLYp>27~3tQhf`BbY|~~06PbVOBxcB|CYFM=N3eU>+T#GnsyGeGNb4pQr%kIBdO1JU zFkVI?vdWbXtb(+1Vp(cKvF>Oj76`f4$xfX%J~Os&Iur`|?ZiUCx@gP8x~R!aUSK4# zsV;OV6*BFKr5c+`wrM#k&?(|?k{y9~INHu+(JBfzIurzH{!ox#qCD8KUMz z5<--;r#8Y=J)S#|)Kz_BO|7GD{+2`2Ak!fTDl;NX)z>>#Ap;XQwaNjG2rqCb8WJy} zXg@eYFWQ*E%!Zlh`|gH%uI{s`&?%XFgQ@srS2)G&1>3&4YW8tr-yr!T%5&hUyl<|W zeVmKFsdns}Z4M2943i*u#%X#3%r-T6BplSD$#As2GO#XL8(5dz1v6v3iL8%Iecz#Q zNO_6EZQ_NSVWQFPi?&28nhM2YiTq59S$Ws>R)<0(Hzx``@@smF9+pf65>;(gp@_iQ zRvl|UvvT73gF2IJgmFfElS4s~I1~jP#S2;<48<{`N4oMD)o15l%X=Nlh=isn;}~AX zBN>_2s#K(_zZ-NaZ_w<>aq_7+pArQaSyxfuadM-k@@mv0cCEITIFu6^VNuQphIO(r z`M_iQPndZmytlFia)_GQbjzjw(k1z<%nWS^s{;lnTYXXzOwm>o!$vUH-IK$cO z!Kve-M6$EH#F`_CF$ywyDyzB5LbWpZ-PlRl7HqyL3y+q2`-(=S$*$u?9 zr5C*?vH>z`qi~nJr1Kq~XBXjWXXD+;{e-mLAb9mldTZ46vmLX)6Ta&lcnUehQLu0E zf=z-8C2#v>hEp*zm}gF!0a?vax^MH+9aa+>2uZD|S&$X&%?^!-gzG5gcceya%~L98 z=U+)DTLqcmQONDQkfQ@NwY5yg&Tu(L%i2b=AYSXxVn{`g!raFTQ{Aq`)@upJaa}T3 z9HbQs0oia}=1?}I#z)y6;AI=D)l|=zS)G&Tdb*1;i1o3vJL>-Nz$kIhLYjV*>z8Fw z-Q)0&2SzzGgRU&=Yn<&4JHk^IHJ>CB#+d*hyz*;0VLW$1c$Q;tUhL2VICuaAgI|j> zvwC!(rlBz>-7(E+AgT|`8#g5sUb zi#IwLsceq~TW3|zoK;(2)gBB*tAa5n>J3?_XQ+@}XVq=r9uqqYC$XS#-EZrih38p2 zt3FF-*%6+yaM7V6VI2Dc!b6%)EdzqHnoeb0a+KTEj0~;o z)M2hyN}Nn%9DsuYAHfSeF_qLkxmq-oh zYeehIjpuTbJ>_f@gpog*DeY#!nN=vwMc>t19?xC0eC|5EZu|DXi(QTbvOxHfm0fz5 zZ{Pm+tc2^cxbf^pmAdV(Npbc#jSGYyi5P@mV{!J5{=@n#R*X};6^{G@!R4=XF@s>ZP}5kCRgoN))vL3W%Q_dfm%5ui z5yc&6*P&o1mapgHe$yw}#l1RrU0$~ILTO_Z4$1@JyB^gE<9SxX*@VhT+;JKo2>#&F z^@h0D_n)|DL*=yChqD1uvPJLfC94Ob0)g} z&a8b|U+wHvvLifYQS%idVVs@_!d?4sV1)5JJK;Pm(YozVe^n%mqZ&c@(nEB@c%Geb z7Eg#>jqA2=KTITyb0I-sOvyvCX+zEHY>7-;QwE z(ucam`r)8b5dOupI$=D|&TCmrK|8{A_uli6NEoN0g78Z(=!Ee+E8+SqOm0Vb%A#fa ziG*$##UxmVVtQ62?ikAgp{(CyeJ=2{+`$)fY+LQXHEL!owal z2w&vFTbf5x*KOY}Wog10y&#+zeH!oM?JP@^vm9r!jqI9w%ED!@NKMTNpLL*47|*je zb*=N#ydB}PrI$V}62|GnsPTO*I$=D|PB;&%w&|K;$;pbNjzRd*FX@EwJS*XRT=7lU z6vxFH<6LDB{?#ca;kXOJxtm~ROD~jioZ%2>5FUM|(bN~R9A}Qq)sTll(sWI6t5{>4 z7!ATdea5VDYxWvv*`H;{Tus*$OX7s%sX_Rcub70hi&JABa@=%HafevrW4m<1Lxz5Z z$uXX1uW=r3z@}@8HIXn5-bRflPA~~;*$L;@$3c-WPWcAm>C;TYK^KH`pPe>cQ!MSN z$C2V7{Mg|pVYa82BIVpHR=bP#^3 z%_Q8Oy{Yq99%{O#c&JDiC$od_eW#g(hh`_7k9Jzre6L6t$H0T|ftTxq@jNTx`aCR< zy6rbf%NRIw9)$mLlTH}VT@cP)EjC?K92RSg1MWds`I*_&;jDzS?Q_Y%)zZNT2W->{ zf4uy3W8`87BRF$)9yV9qKW;citnq`K@Um~}gz-FUjqCH1Vn1>Un>6+qB zk?`V8I^j(-ziKo!n*e8FuDq1QDI(zrC;XSiCgD@E*Eo-*lBO*cT_WK(H}j@`lM~)j z!45ugtZ_beb<>s#Nsdd;)CvFQBa?7;Ic~^j;$_HmRGj!ZKNpPH4q^6`N*ZK+6!gsD~~h@ zvrHjbm@D_i=B6zbl0iTCY`u@ipKcP)ZqVm5KW^Gmkq~PcgtJ?j*<$81aJ4jKs^{x{T>Hn(h8$-f zG8^)l!fdIK+)YPZs1ttmk~0m$+1*XqLPs*xSn_55hZ8=h=q!V<3twh!9tQo^!t+J0 zUVe#Q<7*B&TPM7=@cgV?U7v@|)wH!xVy;n_>VzNM?;L}0cIL{T$2Xm4)R>)y?BnaM(h1*oKPSAk@FEv|oV%mEX=|aB%<&UWxbW-? zj6P<`9G&|(kBNEH*20U$8vo&1y~ZC*yU-wfv5Ok#zQ)V%)_z04qdUUtIy%oev69w8DQ`!a9pXSW!HkH}6qACJJ+!V5*h!`{#dzk0^y z2H^{{6V7L1zNJF)SKt44o$!fUzM&J|Qjy(Xo!9cu)x4Joe3e1?tn5vlk9OKpA+0-&e_tm&AlcIM*^bp)Dw1MTzyE<=<4?R>4Z_K+O`Rb}#$n0$a=t^r%LTk7jl3k| zw3?dg+L~EafgEy59F&oCw&3iht%cH&D{p_QH%#|$wi(jKj$CoJjIuZkR$JTKH>o!B?FNhdh# zqn|KADrebElA(3^;lCpj-=+Kq%S zeNR5o{@2rs83$ec(4QIMm%gVTs4PW2mK-05hO`X}!pU`ZIM@E~f3;#|8mo1jwGZn! z@f?-Ogwts&=*^Qfwk+nscPxrd?1Cy@!n=40r$)8Pz-g@U4D6MixhBl5F@Nf| znoj!&X7D1u#*0{)Q>rQl;W!Z6gR>!X+V?u@X}x<7zW0Bud-aq+E)oIco@>uY4VN9c z)As)I(IresrakcqEAZ$*&8%50SD4$pLiIwv1E(|*a%upl?tSA0y-Yv&g(u9ia0lbr zf=xuN=hVTIvZHcptvf#|W3Bbum-k~Ot36|mu$yR!g7xi*pR3VXBet9$X?4Vgnl%cLy zIkf59JwsTV);~0vwdtX$&dPYWEu`iT1yj3{2@|CBc?ZoI!HReF!L!0RZUE1rEX*w^-j+4!t@VZ2-WzBrM-8a_5h0eWN$9CiPuQP1M;X)?1vhwnB90k-ex4gW(+NNTQCsKjU}h2Hk^7g5h+A;FfXb{fV~2Ysu}MT3UHAC7ZXuA$Kw;= zgBAR?xfazeCQ@OzGJ{K11`(-BDgIQbM^*S+3f{uOg2G!K^DU3~7LIBZ-twAndBwMI zhM)eH2Nct96^L(v9fi04KYQ;2AIVYO3%B-R@2*)turZH-DfKF>WNSt<(rQ<$wbqvR zW!bCUwX|y+c4gC=sgc^6=^l6Y=)rn@Z9)R!h6K0)0^#G06T&3~zQh=u5FjBBARiDQ zTsY}v z<=U)sUDPewNZ2F%lW5e%+whHY*%@%nyvVS{WB>)1mIe#w!3s}B5kKN}9>)VH+l*Ru z-Xpv9i0lq@<@NGAIPePj{bwDAu0VR~hn$ynQO92VA?IZqofkWf^Pv2<&3W9p;zQ2X z4b(-Kf5_RoakKOI){R$w$m!lZc%<;76C`!6cP0l>cmq|23RS^PD7aA-B+jR@!@BGh z>A|tJ>r%&Ys(!psEyRu40vP-mvPA`nIT&?VexG$5r$EGiyz64;aa7#(*2|nOLYR;0l)M0BZP1+wiQajsS@UB-;2p;7k(Q7e7kEQ;as}QD^HGLKYOcWH~Mz^b+rc zm&{`Xr-)OT_kx=xKfc)_jrxue`G9;6X^!EI2hv=atA5Uv$BS7dk?Qh_MVx zKz5AZ`Q$-wqhSS&-hl@s^)}|T5$+S99{#pd0Dde;#ozYSH_24|RrGl=5ZI_WWz*o1 z!m$T`i1oh&^>5PkV_q1)^M^@*2Z6w5jQ|L6gnydpdKvF1Z{E*X7REO&e}hTGvzYj&R#_ zxg#e#;$rH=ag6*t2pcto4V@qm8;<1w*Z>r|GyuW4nc8WH<9@NIe&g9_6N5t&9 z`4Q-rk2qU5U-F2v^`cFWINc63cIX{2=GJ^Y{rwx}J;$LQe^7ouyV-I6ZNuc?vz^D^ z(&cnJjj$CY&Cm}Lb~pR~QZpNuiANk~%dbDhaVBKqTODWX)wjx*x5<~M<=+ou@(v}qXUf0Nk$C1z;u!L3!|-g zwtO?P-H4AH@Uh= zf2iE-XjXQ>!-}6fv+^(f(l3$p`OjkIYdW$rNw9VC@--cKnP6N1Gdtix2mH60KoA2$ zQes);RjUz?;{sM{yX#UX$6q`k)@k`2Gdjd99?a-f`5iO5`i>dBCf~z8puWSxa<_bs zIp!|;{p?1^sb|c&u&3BABwM@S{Jv+?hiex(Xi56P+`nbktKRK57k8s!&#v+sCZAE( z3gRZO_%)wbnQZ0hwd&fiN?l!TbzP$Cs)v;v(6-5T>qZ;&;~!b08CPo1v7hilJ*;^3 zYEBilXX4gPb`_?AC!WCfHtes`Rrt-tU4@3%Z1U=wb!^VBLp*EL!El?jm(+6Faie9Y z-FlH-2iBhU(^kjTx*f24dQp{yL4Aeg)xzvrVC>R-#k#gXvff(43T**+2qmA5-~{e{ zwp|M>W>zg`e#X<*mdkWoj!zx9dE($*Ii#`=)^FWvgTLW%y9qhqFV*08&xQd9k3_=* zQP@iSU{3ulB;IVD%taXIeG(-8_BoS-8>AL>C9ESb5+f7ZanZ@JaQlg4BwR4|GO~1^Y`iVGX&vc0b%PF$S~miS;rwu&Q*@n z^)w;pw)_p?VroOLzVelh^J)C}LwsEAI9spU=r~)e8z5mJ<(9mpGG7g~`D(XpHvaCG z2yb?rE=Wr3o0M9P^Hi9V$;1lF>-8G|8oSa!shi|wT$$(9R-H%Cc_Ea4Qi6q0hW?5N zjaZi7(U^D1??CJG^80ff$N6pf9rmyH$nVd!zF)H$@Wtw(*yU_>2D+Rr&ir?$%3aQu z{&#F}2J!pP>wW{4Z!#v_>o{A!vC!qrVU8gKB-r3-cZdt#*(ti=oyC>NZzhE2aiqPO~3A@6sq^&v1vOW_G7VtL(9R|Wpsrm z`NgR0BO9Fz$=QL3dkJTag{mL1S}UOYE?5{aY%V9QCTi~+h*#o-H)Myfs1>jZmAjkD z-L1;)177(_cZb2<66EJCL^s_g3G~;!zTHJH`Or_BF4~e$sKIH)<*XJ)ifIn;DDi84 z#Y=e14&bub!*ws>?6#Iy-HX;-CtEWhxQCsk_K5y0*roTeb7)VGx~%z&H8av6va zz9t{xo@t)6n(PSO*2@kBi+&Ua*zl%45hRX*?Pxx>lLb-q0ImP`QD5knhg(5KqJ7!; zWMP^oBJ-hOF$dW#snPY^e0*IopbvU0?7%#)EU?3db*4$)5VnJ(;{IXzZX$>iuU;1& zu#feKoawjVm8*dzK}n@yOJO$ht8=`-my;@Alv0$;A2Oj4C%$@(%>nbefXj{|zsglI zrbwB*SoeZhy@x=bO?aHB7m(z$$vkbMs&`oL%fihtN-9ATDeavsB32q-){wB*B2#Kr zY)R2$y=|DcsI|hQWT0XoKU2MnE4+Dk#k)I+ydd_(?K%n^$V3HWoD!4od6Wv!>HtD1$uhhdiKTzdBzv_IYIpEcKr0YQU(%VYi=Ru-0 z0@`V}-rpTI>24yOPPQ~ai+J5z(XVwS^jcL77Ng9f#RIc`Q1t`dqHMCLOT)zWmt9&U z-yL&FASZ-AhR zxyWnIV{L#X^+3ZjybgXyr_P4U1|-}_(#e%(tHB!zmG<;`?$wj|&gp*5vruj?e{YMo zO#RT_b^S!@3<9avi40Xwb6igGbp1IQ(g;A-q??4koDY+@872alYAeKzN+5aSD|-qh zQN;!9pU$2LU|i zFwW)QbDJjzW5;<*mvf_29xB%=e9xYdU8VBwk-dApVXssgEDd>kd95;1s+C9h>}++< z@bE}!Pk9foR?5S}L&GDby+fsuq20U^IdB-kZqz+kUp=WacJ-0Y=u`wDpfu-Qrf+X@2>FSGT&X@ySrQ|?X7v0y(1&L_l}HsrIFc6xi;d} zcJG!z<F5xT*BwP4C#y3&PtUP^|MO{I-RGQo#*1&e_Th=Qec&m-`S$m}`|#Y`zdZOmA9(#=j`hCc zJsyT5VAMaOz?yW~%AeChrz=eBHq$=6GNb=AP{{L}}Z^0e8dXUw|Nf81hu(j~QGWE{#wU&!w@kd_Tfg#aFZzk&4|w1DXa4?g2LF2FwXb~L zGoJPN&A<7PFAV*UFMR#?fA!~owD_$%Ha+!41GoR>gWrgIpa12qfBfDpkG^ZunOjQ- zu726xM|XbZQ*Zq7x1Ii{>z?-U-+iO^*LQs7u`Mrs&GE&bdc5~vA366Idm7*Q> z`Inh+=`$~X^xUsCPd)hlAG?+P{_C&(+7}+a;ZuL{(HA~;$-95#z`2KS>bm~2S3a%p z@|_-z-QR2 zUjN+3U;OpN`}~K#`{|DrEWwl8?Me(0n3J#qQ_p7Msjd-21+c=`K(>~n{D zCm$Mh|MF+Q{_>$KPyPD`!slMU^q#Zde$|IR@rf_~`_I4gpT4)_y|0*k<<>6`UF!04 zFaEu6{nd2u?U(L<1ApzW&;QGtf8{S8=)dv!_^&?jivRwT|8nY`{F;w#`s|Os^V{$K z+&%ldKKa#yzkcA4uI<|J;DgSm|KU%{cmMhSzQcdx+$&2Te)ZHvi*Nq$;zxh>)Md9l z_RU{<(S{o?`S`2ecK9b=`J8`!?gL+a=D&US;FtSL z-1FGKe(BqreqrSQy8gNs%?!Q%&)9V6A*!WwM#eX~T;MR{G zTl@n5$4@`<(aN`e`rZHht{?x&i{AgaqD2&-_+p=+Z;C)UKT#tz9|#)ffE9N8j+_FWvSBAOG&}Z~6L_zwo@7$*z>vKNwhF4F0?Gyj|O4 zKXmZRz1LjvJLkSKGV`@}RxYn}{p%N=^Q@0N<11G@`-s`;7nR)2L z-+cNNx8C(LpR2s@V?S|GykY#4-~G+ke`DfpKl{@E_{Z0L;T0b{`;mk1{Nxkwec#VN zaOnPTUG^(a*}c5<4>ND*dS>#@w}CUXMK1P!m!v=m6p1Pva~LoL&C99E{lOPY4h_k|8=T+1(s4e1CAF$cRRmKYe7yi{GXabJrUi^Jxrl%@n>M!BZb)NtG3AMp zxQTfl1m?3zq2krKULmOj*y2(NSURCZ-CN<&o@Nv#q3&u`h?JZp;#!@+^p8S|%XKdp zSWI|RmjTZNJRy_lAo_R0ahx~F{<_5>>n}aZI08oO}Gnob#;*|$z9cOzMoaY z`9dqIkIg4ZGaelnhL=)(ABioeI?;#t!vBHHZuMws^GC&w?=VYxwIm_?WRz z6{_Jpn>ew!i%ntDf0P78`nl`|AmZ8&~2wc&;NSWd2i z+wJoFE$67UV3qB?Yo6>vo_#GMnY%yq-Z0b&g zLBvX`c|qdEIu&dl4G+vUnuU8pV+Dd*U==ckiwxbB1z1rdgU2d87WvH-9W#AS$r&nU z>P8l?Wkz2PgzUhP=+Wq%oog;O>l$-OVM?l31#b4ZloX-#l-(s;P;j#$rR;kRSfqz7 z%|W(Ep_*;}%O<9*h}lGHuIdWe@4DW!oe?G+CC6;@pIwUNTM8R!lByJ?CM|6lCE9vb zzlD)j2^-cTgDUf?i`9W<#B09V%oa4I_wo>i!W|2MC~SlpI0UrZq(sT5vJ44YM%O?B=#>~FX1kUL&13E>3A5=h#FE%8}$EQ*;>!<2&*kC`8ctndnB z@Cw_$Z3jEa?1I+U(a3Q&IK1}G| zwMy7PzN3DekeVMmOY?qZo-O(H zI-BLdnOB(~DC8x!686dQsUwF@mYFMHrUSaT8U>MUkeMreQ>Xy=bLyJsY{p%g zcI5#ZW^Ry3-2>Xq>JWD`cc~R8UZSwf1G$H}$dZX+lSOWXx!L#u*(`gRyR-(Ba*4Td zJwK*^btVa#688*gTw~tlBv9rYZ zb8N|r0za5z?lF=Jda%pQ`IBUXT(?egYD>+qaz~0_>0; z3Xr&}2!RXhbzVtW1FmBLi)B~5ecNa)jJQ{sXFl_TG3xhf5VH!o5>a0x0YUzFQ z%b@x)q`vG@Uxw9}-RjF8^<_kT*{i;kOZuCJUDm+M8hUwGpUa;2Jl2z}G&#GUxp(!B z-**6Vz3)tq%Vs3s(Rew+6E<;zfdMeT)S|G#l6fWHL5}&bUIpp=fF-=q3?naEVY4mx z5^5&8iGGT)U}%Dgt;c5&C}5>3w#^xR7BED|%B4n}>IuI_9kGJp>D43dRaa=3@?}3x z;(j0&u;aJ(voM+G(UKo?=FbIT#96h~tivbC4}8MaS0`9y@HHI&^C*wN!hn3(9KK=6ZF$a-Bdr=qTvQPyME zAu)FQ6u|Ln6o~nD9}Efe085`p2x+zOGQ(*Lbx$xLA$-z_T^4-&|QH&1>{+%cOZ-49#meU-Q~# zKtSvI%nwEDT1%tC&AHH_eo$%@e76gA9wc5dYGvp1LFR@FIq!#40CPf zVqRdI&6B5$r8BLmK&7*H(xB40I;v3VZ23A=I#0e5mCmz%Eh5Uz7UJ(xkNfHww@XPmy|3s8SGU!q@Y^LX%pTs*|2m$xm9(sg=&tDq8kmuON-q z!#Sl6lt-<3pFurWw12YcPHB=4X7GN}X;yw`E+AZ=e9F~MpmcK>C&FeVl+z?+&@-ft zN9x*Z9cACTT4`9B(+;+p^-C3@X5IO6p=NER6At-mR`%2chc74eNwWl~;e-WL!OQ4$ z1xW}xVR2-e!s^)ytK1_GHf~Gzf1XsoOMsIDkFk%K11_+*JuMdmRKU+}-NEjN{3H?Q z*H6s*^}63=(@7LIW_g71#Rf~|y%9u==%=T+822RM*fudJlEGOPOmXDeaLn9pYG936O13pNZa-CR+e#bJXF z1bk_r7S^jgB1;^t{OfhXO}vg-GVdiU;JgYjvs{}uq=61-_%*A9US!b%i&y(;ofpeR zRTbjJ2p^Y@vS2-YMxv#TrHDoK_HD|iUmSK3#tp_8+rfIuEaEjTRDUd<{Gi!N*rFHt zqSf=9Ay5-*dT}glh)Kv=SRFFPqz)SJrNh*I)&nDgNZY}d_|AGArA1#Dm?4Web|V>& zqA+3&9>Z=UsnqaRm>2ozOsfjYIT_Dc;3dHXcCCbYEJlna9N`hGz$yy`O#{9pdx8dI zKZE6dkuyJ0sQN`-WG?k4ju8yFY?fET29K?mFwUUOOY?r6v)w{6UmL>E+7?8MxirohhhsEdm( z7Vz?+;a26dtvTk>FdAh&3Q8(p#FJKJGl2wRbr#r@%nPzJV7+0~jwF<#LGqd~{v(}| zMa_5P_uY6=OqLT=E^_Z+G^k22(zJrQzrgD&Qr?739^mWECr_SW5x*DV(&A#Vn5w4c zE$~xQN0|%9p3#8;9iw8jG!V~+t$MW(gh_!!Qo3e|XRTGQpX7}uB3ZFsLs(V>`?DhJ zQ7wUKL?KOr+Q*g!3?iV7keY%Lei*QM9Jmgo%-O+S=*5LauioM>B=az0jN;H<(u$2J zA)(%cA;%BqR832f*MzGc?S!xwj#fiM<0{j@p+#Z`KE`#5c+aoFMvT7?L)7V(4SSpocrdpgvY1Ru5odlJ?1Yevyb5QEB9$Z40v`hua@wL4VT!ptW+$=!qORIPTd)^SUtQ=F&>1ixp~vqcu0IJ5y0GIW|FC3tdM=wn(Dp8niy<}L9nor5G>a&T{6{*Y+Cr3 zR2a|YGb&8FXss>7FyRPlDXLw^%4DWw%m}Dl5k~Bn)j4=os~Sr8aJO%RR_T0An-8C* z)X1EZrnVCK?tg!kj~(2nb-&uj4(?N+O!nj}xL4-Df;M^c)*aRf)$QA8Ob&=K*$As# z_$<;WRNjjf5B`5~vFgwH_y!x?fbs?ur!L_OcwoF(iIQTIH}-AcHh_%stnGl0k%v8{ zIxj$~YgfX&!lXwv=OZuXV=lNrU?|1Lg`;?6@Z{0ysp;|Qo5u%-cMp~ZO9#fwh4KaB zyau$kM(hxWj8$uL=}of=+(p+x@FPPfk4_&taA5l8@u87jZLM+7uLstE#@d<#>#95j zJKm6IV^2l(ecQL~5I&H`{0f)RW7t@5kDQz?fKdulWpD}lcE>90*V|)*#tcbpD5gmT z6+?5!>ddC|wzXmh4R-~~MsU}Y9l<-FBnbL&UJE!JJ2J$an4UT!y8F&2X?I%~4n9f9 znW5oy;zc!|*Qzs;mDH&c??9q37=oM=rONe50?tU1FWDF>ai6b zlTUQRTSi>JN-K(ZkdOns&*QOjsic#|jvI0XTpR`;8!TZl3x9Z-s^_S6dDyc>9{IHu zDi2u#Y)F16v=N7=qSn5rEguNA)mkpnf7lW>jTNPAj{=#EmM~+hpr#!R-1NZ!>FqBh zq(qJsc!OOB^eAH9+UQZX?-RX2*m9J~EQbh#yGy%AckL;a#K&m4TwX_&FdmJKkB^U^ zC-73~{DFg48F*E0?vA--L79FwQXDDnD(7m`cgBZHYE z9P*5aIS3@t1)Gi(N1p8HD(cEn^#evX_q@sK418oLLtt?-rH#IOi}c@nJdFG3=^oS5tjFp`fdn=% zR?Pz1W-!ffm~gr*)WWDBeZfGBT=046WJ-xe)fE=pcppognwOv*&1S zDoLG9bYr2@x}#^^1-{~ry6!&alFgRBpW7#kLp|y3Nfj^bcP;9;eRa@??w62 zcZ&i5@ta(^LkiL3(@cbL6BeFPL|>zN)DH52u(=Z94m8$V>0^VX(r{t0G`O2l+#@Ce zAKggdkBU)izi=Q#Su6+rh{w8~ek{#mKMcn96va-q<o*7hw477e+u#4m)lI;>P{AfD{@ubebQQCT%BCo22nzNqP zS@12zRlJs(&UVmt;;SrUaubvgA^>Rg%5;{Mi>ZtF9isA z{vn{E9U+kCuwUmUN8$O0l<_T-E12UEZBR0omv_}_6|XuxTPh6>?-?qWO1mqbw`<5N z50<^b!RiR#yQfsD?W)c0t<*+_2WzE4Z%=8&^M0tO^$PyR$97p7=o_iCS?|@Pf*G7-7~NV=leoRhQj&A3I~VofumK z2!#)G`*8GuHVG~mz!-DAdfn~AX$l(wBM0qP%a+*E5Y9efAU15M;a1;*$@jBTpOTEU zLkA7bouIuQC{Y%8c-e@7VAQ={_e^l6T@Z~i+6K?Ep4x)5_X~2xSay>@F z9X8~4Gq$`V?8Va2%9XGc*?kaqi-E`(^cq4i&T$#lnw5Z?nDV_S0R(Pc+q z#z8$&o$Y>W2cy{;11?=&pS)DqW8DO@jP)q`kSn}6jVGgri>|Rauf0l4>K$tna#mHj zI_?lW9RZCg7#EC@YOX{{w)sL(Qjj#^ES&NgRGNjPMAW@5SpyAMUEr!QCGw^MTkm6M zr1(g`w!o;qT}R;U?}IPfV{YfLXFI2)nKKVa8;`bgBqAX2Xwj>Wm2s6whJ{s65XZLn z#nI5C)6wGoGwBCM9%ssX*_JgSJ1f1+Oj~eA!uiMzLWpTenbYbH0nX6^>F*^M1}uqM zLZ`CLt2z195{Cc?Z%#50O~!L9u2lAl_#ZCDu*$ZA*Wx4 zg_jr!#vawgF=`|oSI(}ZWSSYUM*i!Wf{x=#Re)SPg`hX{L3*eO1{o^F`!YSeraD0c znAsJJCj$8sybScx`Q)tuyuTi1q0_?zP5eajwlS1Vk2l(iU)?2tcioF}lrQ#6%KT<9>TeCO>pnZea$O;Rx zxE(JA5@3j)yRTC8)aQpX`jbu5lUIoSsyFTuG<`m3TCgpqxM@PDZ(>~o>So`;g!=X? zcXUT_1^OtNLSa-ACi~;llKaV+YQsVvA#fF=k1ADBR3=lAug&hdXMJ|pJ4B?8QFbs4 z5XPrfnHOA%13leYBNM8fqCf^pM(<#Zof&|nmgf+wI3PkcGpW^{it1zw6gP<|BP`sl zi3x#xBa9Qc{mKm~xSGp*MQJ*QiZ z_;&IJQWKS_Q52Wf{R2}+534L1g3zeri9pt*GN5?}=>&wZn~oZw6f!}i(agwpD57Qy zk-U`G%~ce)=xq!G=eWH3qp;tsS7~wD*N#p-oFgVYj+hE?J@>;PX1%yap`X!p2;#_3 z!Wm5GttK3H`&1N?7S1(!FyfPoM0-b0QCqV=q z7$OdGugZFrPjM7iihL=I8pSH7U|<6W58ZU?NO3-C)OS$Pf+*UD3e_A@59hEyM>9kc zHvLLGCg#k3QJZMkSc5mhXeDJfRe`2XHRmF)%2RyQ67Td~q2%8zHqb&+JXOCR3=y`B zxpy3&y7kD^@lz)tfJ_(D?K?+A@cfe@cCM!7yw2w$uVHFFDc_t77kDsHW$wt(-qOhKk)gp|qvPX8hVHJG=WDl54NmTE9vPoI zcQ%bzifuv>(%RhM6@hb(Vcd#`{u(2zb~xS{0gTM2JkUNA(p%b zc_L(mXcvhJfv)NgR40%<8P3h&7%0@7B*YDhbU-p*Y0QRo1cOU+hDA%e%J>dHnV*(r zWP^%a6P3N=;7i#?UX3^cG1H! zaIz`uHT|OB^lK}{Fq)G)EIW3n<+9vBF0vD09Q!yAOS}2;DCWx9I`5}*G6n37^)noy z^n-(K?2ZCeTBsfezPwNPnEZ|>FMd4*{yt~9nE+iukGrs&43OFBS*&~YHVe( zqC%8dHQF7TUYPU(Z;nSDDnph@FG#iKix8)^a?R= zdbpvk$`B_an1enfysyHVd_|(pf`JP%g{qH;0I*_8NeT8G4_0uTR`Mgx^TL--gj5xl ztt#ssV1@nc?mm-RCPF!+xg5Ar_*d6!C74gbR#J@o zTEF!(tXJ_$4FC*2V>G2%#tT+hh0H2ykqU%z9bYW^JE$XNGQTsG5> zefJB3dB1yCF3>Y)iq(Ol%Vxx)J7@C}zCe1r2Ik+Ky&7?G=*c6Zirc*?CS=dMq}U0a zQ8vyUjE#nYID302il8xy#%B104Mt)FsRpLu_SJan3Q^cQY z1#*B8joJ|IK-VR|n#{9?7cKCJopCLs^Jy;ZphClq{W&=GEpZYD6iQQ?Kg_%=>{4n1 zmjOql*NCxObqfo<;81BmCkIt!alJ~Ktx^`YfA||^HM~k$VYS^4Ja5|!?|a`n$qxIm z1z|IM0c?h2w#{&Rsw^yq={K+!R{tj5#~3-e_ChgafdsNhc9#24+FYmy!a5x;2g?Aq zio<2UG3IMmwL{B(a{N|3@w7RaWqsWAij>?Fr&_@+;VkQ!hKR!U1Pvt7I#%N(T zQ=8J)&DjB8YVafwU|k`{Y}unK`}92G0H`21>Mbj=@(8jU_*K40M>}ZeN}o@#4_7cc z!a?3?c1=n~>oS)6FrkK}Y^K10Rx}<}=1rMYJzi9q_hC_JMIw4Zduc@_U1v2fc)!^c#FS z@fz?10prW%H4|(YGs}8TN}%;ySdlYQ5NIyhAvQHT#TR|J-CK2_$m}$a ze6N12g#dHewA*GbvlQzF%#n_7Ooie9znhpFS(x=}bN zve^fcEco(-x#$+d%%&DGZKQovY*A$TJ@xu{z1l|76F6#iD_^-Cp_itUFtT~nvZGk& z9pQ;cXruL^xZ*YW;V_!wbBC6#BA9u}Q^9(7pw7JjYd!>)%D$KLt0L5ac`x!R36G|D zv+h-F9CgxUtDgAHx{c`}AA3i~?OG3$Y2c_&Zr}>MZqZ-~;Ksp47Dh)R4t7_$Cu%3> zd2mR0xvQ6x<9AwFCMV#Zr_ye2HM{^*9PEVxv`L(Z54Y;|l>;JV0LRHdRc<0acx)O+ z_v+ZLPbHAlSP3e*FDc?<8j#9A#bcfvOVXnkqrF2-Na~0m5*1(zk;#RFzD@F}M)o&) z-70{eN4PEKPX+$+;K9%y6sMy4p`aopf+7%M7e*OyVsso0EB4F)6Pns5vZ}VN_)tV> zl-`Czyd!1|G&3R+43SJl8g5n%eloY1rYnwL{4#v^ekTvvqXgu!DZ{#v{#|lg-PlqGD1qa{^;M3V__6?kV9MLXWIgo;?u1 z`VgboxVMWyC2|6>mci}k{M1g6@-U|*Os0JI80$%)tyVNxf@cqDsufDQDhfv-H=V}P zz|Jvw7_;-aRn(J93~ZPP%wh$dCE;iWUE{mNu&<-ZB&ONb$pb}L7f=MXP7te;n8G_R z7fD%-EG(@z3KX2xWnmjNaT5B(!d&JsbO$<+cz}fz#%M_pc;*SLvRy>1-D9fg)k}eN zrwxe1dFwcOj5Bs3WFyW}ivv950k~?X=2Gj7g_vY+c&aum3I z7hZ!DO{O9(9`Y>(Fi)OeQ&Q_2cON^Qo)Km)7^K13647-J4h(ISQDdLvyNdE_4>YF3pF_5ulVyQO6wuxNvz1Awc6 ztn>y_WKg}dY}tk?(P>r+7Km8u$~jUerAPhwM?j!)qXV9_4<5k`=NY~MrxOsEf#T?< zTbQyFWRo(cf^4!JwuhJ6s53Pyo$*8(k;x*S+&F0~Carbp_rfF~>uO7q!>?1aWlTsR zk=9?WhNX=ea)hL7O=rnX%Pj|fvTPn!rIxKo^OKlF)E2lFDl*nT?43f{QtGt|U1PG^ z@<-*xh_LZsy*;X+Jo8+oV^>Paq5|m#%eJLU8bK<^jC#_=*y$dN=&UE5s(`w^E_3@_ zCf5e3`cQn1#l76 zKu_x-ZKdW-!a2cR>_av>%CYK6l0)bV6Emr>--RVyDe_dk>~}NT+lt_hLzoLy&jV>) z$`%A|C1Wxu76P&;TE)fuPc}y_DcTCFD3LWkYAkt?W<0GwP!6JJL=NK~T^hO5(j)tjNgXuo{pF7CuqR)P;Z`!dTp`8C+>WRx`0@ zCv_vaeQop*V{6tLh+>5{MTv0U!FrHj%F$a@#+F>!1bZ5_@*9=KdTCF^_G^3lz-Tvl z8we)#gg;yNE5bXM$56&VV+GZi*Hn+&scOS8{nEA|8%QbJv^4?Z>IqSPy_2Vs*fO%4 z;imSvQ)ZnG8cmV`L8D2VjwzGJ`fViCcF5N$abpIQUDGb+;szybwT`;RgHrglz%Qhz z!hW1)J%&g+7)5Un&@AkCK?j&>-98!ALzQD~6~e&~Sx4Ot#f$KhAwcV`y%GkAS4q}U z`2msBuG=o0Q#E7m&0bW+lrfs6h)qYx4BBoUrKP_;Z1TyOEsU8%msQ)z6uDxpYH7To z|J3Fk71Qxr^1BY1&ERYAHCLE0Qn}E%f<&fk*sAbT^SKE3Vi0R%4bV`O(1gfL7OH-M zi2{}1!rmUK)E4%;K^;Ew>tGO|Ad7)XTq;MT$OC5xBEKo?d>gCe4jzNw4;DQMEsLGx zh>QSG6P#S&xO%=+wopZL)8`oopqbqJNFdTf@+*Ztj>eEWPa>4>rokzn1n&Afm`He*kFmx zkl*T=Dksz zv=*0^S6);q4-V}b-o0mJuZUhG=pqeKmRlXR=FleVm1&C5dZe!$p$F7~UP`O7_I-sK zBFHa2Xt5uxzGtm%O1UMKmo#eaqz9KjTtA<6gu5r4wcV73$F7NmM95Q%03f$Cd7&az z+Au8hpyHTbq!;$PO%FE?5a*9E*GK$RSo_w7pNiI0^s8ez5NFido9Lx7fM-QixOzC} zLqDP#tyKX0`7(wz4qWm5Xvk(Qb0@< zf>|c$!b7^aP%F|$F(Hh~uPpJ4fprw$S$whT0By(FH28FD* zM}WVU4NCb-QPFxN;zi~b_6xm@5EVOJV*Ci~POdchaRi=J9Ni;2CbhUY$^)Py1J32; zkOahxW)oB}DeIB7NMt2!+8&fCh%1PAy(vS89^$w1m3~2JKNyqMo4%5UgdVk?QD55U z37Tor2qH`}>$#P$Xj0;8ElrS`NpPUWHB+)>p=>4L|VX zgh%8GXJojwEvDscDz*a7OgFsBA`hxz6jNjc9EH&=*3+pP)&u;(VX%^=XG}6#;Oa!r z!pju~P-DbbTx>`6(@mwzzQlRTsa>v)wTk*kaY^%+F#s-!2r9yHNI6%*O++4_sHWl( ziql2PX#|f9HD%cYHLD9Le>+hMENI8p0mUeGEQpIxnv(lKqY@jzSq2dS?c6Fj51 ze<28$=m;tTPtSTWH&hkJmn>kZPC85{ykMNAsI&&MedtSff+UaI3Pgnh3Bj_6)MRfN zlk2t~b!JfHd)*WDr50i5usrYWEUA$t9GUb8qlyvUAjLb_K@qA1?9j?q%L= zMcs2yri&T|t-W9owrnnxH&MIiBr96OtW!5eD;O6D1VI5AShEGoFPk_aW5rZuYzADu zQnJFMDZde_2>5`AN*_A3@V+<)jEP9m3OU~^UhONbZ zfgSFf^(v0MP|CQGp|alJgk(%wA!TeD9wowu#8I?bqEUwu`-g&KW*}m6E6;J$i*LNOlo;3 z)5T&$XjEj;QHw*FKHc;x-$ zSFBr(wHlU7Dv=Ff+>$F=EDA?FHit2RVJ}>OqvSf2?_(0ybP~h!oZB1&oT-_2ffGR0tb+v*=SxQzWYb!mk^OOqJ)^mu*<0mT?%`>uq zj-95ZMMfG-@;LV9Qu0Fgn^f{lq`uS$H?P%^!&I^wSAZbD+qDAC$FSs+s39voE5}IZ>Ly|nYr&d>a)(OL~VpL$WNnSN$ zY`U3&d@9BX%1%RB*>ugd%4$Ww%8-ePoc0C&z8X4JL8cAREvf8~im8f2*%A;Z0$Z~$g>7p7c>xzIg zDVv;8Q8k;vX$n^xF_E3kdoe@UMYM<2>Rvq0M2lu|kBn{3b$#6Ffap4{h*xRpp>Ve> z5bVIzQ3`n^;43FAArb^V#nfdnjx~b`6H5oYkA*h7&H0NwQ1FfI-xzglF$C^XR|c)x zCze+BgScsE-S-SBE=*rkw9exBw+u<8E5m_n-Z5kbw7OqNk9k97=`<(pW_HJBs z039w^l(9BLNu*|n(Cr?by0peSZThA*WmoBDA*SV-5y9KHd-cM8*IS@1V9aUch?1XX zzm2IxiZw0i(zzp0Zp;QGtIoM9MJrDeaopn3fn#DeZ3{1u!po<;*c&SBcMlxXKB%@G zC!eP)^9XBGg7Hm9^7*+dbmJe9@5!#b*M*%A=; z0V%0cc_+tBnOwzXN`(V&5hsI~jM58uT9hjq-^9dht z1rKA33|EzkLpT155bSvDo;VCx@7dJQIR|T)?oMVd-q5_2Fv?Y4POjm}<(mGrc|8rB)u_Kij)Ijmn?T5yTHPi?FrsjnqU*-5Hst zcKXC>9*sy)u1oo_hfaC{)Yc&>9jnt#h4=TmcVz{ed-v&5Veia!u!qRiOvmo9X14Xs z4J=L&SGE;swc7MX`{)$fqq^G>l}X1#YfiEk2slNtc9XOYz*1U`nwqnci<}avZj1Vo zFap7K=pPz*M*o=f5`?VN&TQK7p^O@8u1u*0>B(PeGN2BO4IOCHYhgduBkB#K^p&Oh zEeI(yks?~M>}kprPZhSYoe|ZkaeFLe4Ky`7Pu0R!V0l(3QW^m*D4e6LrP{e#AEh!v z`4pH_6QS2C3a3P>TxoRdSrvRs`449Mb=7T!^j?5ANkamVpIE@Oru5MVRg_-^^=!JxnPmWj}7Qt{LXXpU2f>>a5ILEIBRi-6RIqeUMc<4ag} zi@h+phsT&9g5-PLAw)NoWlolfO619S8D7*VyBBco3|uVl3e{dksj=1`U@BXmQ2|p0 z*Re2AHtkfoHa#_!Dg&<>9E`(TDqmVeNUF9kJyT_rMx~C>q!P1XzYyEYV9_bMm&wr< z!OJ8`hA@g zO97AcFBvk|O~*0D={L+CbZ@H}z{CJji6b$c3e?m#7H^^pK-9Vkp_)^NLxp&l;s|pl z%38C4Oce)Yao7%%w4`YEG_VleTBqvC4B*rjhgf1s=sKev;V0!HB{Ra=rNdHjo>vy) zRwFJ#PbbYPUksQIGMy`Tld!fS89;NT0w|Vftw@E*f>)mG0J$?^&_4~G)2td0VqLBq z((Z_BucfU;#rZF**W-(&6-;{#V9_L{L?9f!j3z}f-WAt%9+rkn+N1t=2+VFrV%G*d zF{-4+Dm{|z$mxRhGNnW)JSIY7q;{3`wUxq#DTkP)bxVGm4qH)$AL9tVA~{y+#O4;# z%!wRz3#Vm1R~Ogb-|L<^GfT{=+l2#~UW4N$C1OQsM48nh2{%g$Rh^`U{HX~drD3YR zW?1(tE8@(YZib+QOtOu$c+5~qvBe1h@_EdveyzsEMWv#K83LEKr3!)_Qf*5z-j5Vsm(2nQ1JY7_W zwrz8UkOu@8s~X+5Y+u=YX!RD6B5pOv0KbkN6YC)!_cLM*Ts~{r`ib1a*p=!xtLM^P zm`^WDwV{UXPw$dZEvqS6ibArZ(%@XW3l#D)*OL%WhY@>W+Lw5Av-OvJH+RjhH+eB# z6lrhSXWC^kVB36c$uJG_RHUvXT?J^0SKGkKD^1mmfhVP1D6EU>fToa)T1X?dJc)3P zi#^yn&|Rw)Hh(HwSQYfqF3_qfhemgb$GDpB`_L@d4_3F(T9FcN0z(ss6FNi<2Vv&9 zIyP!#oK&Xtlq=S7-lh?teTWVy}1KNvTMh#5a$_a2tm=adn6^6bdT?}PdXTc zh1meA5jH=mhvh0pSmZ?XQMRkJt8G5bJ;#Da4=qK)961Rprk4ph@H_A!MgB*ttF1<3 zrHC_;A?}rukpd_<$qgB4m{Gf=MN?vC(PRCM(v#P!lim+?<|5Nc9p?!Za_ts2^>m=^ zc(n@Wnt85Rs^JAK9J9KCO)vOO6$Do>$4;S^jA4%1i6}@?2hC1J7DHHHJK6LVbIPej zG{}soHk%PdbUk@Y0k4w~ZeEAeoyBmgqN0ms;_Iwl*oWjh^_X~a+3Wlo zC89?&T#c;Tl7y_i6>E(UOTNmLtL|9i1Fx2RI6ARQ2EJEBJn(*^#X*I-q|C+@9bl0m16dBs5L@&HFkVF+1Any z77r}LUx$T%k+m645LR)qMOmd&g^@xH1?99q8&+5P71?P|1aAG%tMbX)d6v`8!Ac0zV@u*R zZrbQTt%uaetRzGetZdz5$kOx?JH#d*m{%Nex8J&>?uCP~?ODQ#FHCEG~~kqpmcaC-=}H6-nuEuIu+MdtRirFkC`E+$vl22a@R3R?+V zh?p5CUR|i_#ST)c(=P>th zGn^IlMD^mq$&?|~%pW>Hn%R{o?C+6)U_TvWE^a@O{;2u6I$BOh_E=c==siA=Yah1EH>K_4fkx{7;Ml9`$GFC(n#W#<|L<3Lf$pKNi8jPSm>CZU-A-}5r0;y0 zOEpT3#`M0UtuCO4XxL?S;11LfcMl1zNL;18ekm(LNOWJ&K+!G2kt5mx>=m)$jom<) z2GTQv8U5`lQRnFcJf$kkEV(foitWPOisaOoNi-8?%1SF13h=)$`_~%(wC<0!X`kvh zTBBLZpP4ob0QGyyU_peyXv|xOrLa=KEVV6Fj+SJZ6BbZcZ1aeyO&m4T6`~++eZH>| zR{I8uImknBb&unR0lr z27qJ{ir)suGXqrx{>+eA^t7qchN<5c_8VnjLWLp}Pim7Dk7|?(C#r!+i%EO9H}M$K zS}QD57#9%I^^iH_BoLU zz#?A26rRdr)P@|MNrnGSo!mD=n|4EtWRbH=uC#&>JuGv&&Xvs}O^QUL z9M|H#DXqqZ9sK3IJLwo-iirz_K#u7oYmhnUqs_}iv^JKJvMrOSg#slbdI3#ZN^Lo` z>?g+qaZfYrv3|j*0}V12@1V_fS5JUS$-!N8xdCUS0&Z4AgpVv{F0IgtbSjpB&_tBC zc(055W(#!T>?oV`7osrn7sLTJ1*x!K-{V9whPu&8gkjrHcm+n0f>_dM`5^BlkZmb4 zcR=hq_rgUm9vv9)8i+AjT=c48T#Q-+`&h&CgMp!4<-G$#oR|0R87cMAc%v>8Jpx<4 zQWs>iMNm#MESq3YV%*BnDl?w&l7x#O-kG4l83jR`s0HXARZzuY_2GjAEEFwIi%`&( z;vuV)dk~rMp&9seZ-fZaj8WJL8G_Y@i;fAaaG`u^et}#NjnIZ@@za>$#czoNDQU_C zFH#g@=V0Zl^D*T^q?6$-B-l`%gE$RFGkuo5#5=$LNSjl^(`~MXi;FxfK*{R!1WoOc3?*wF5J{;0 zM7U%x(d0&k39T*mZsc$1*bmRbfh|GXe5yKK#4P~ zkj1AVSb5ZucSW{pLt^yO{QKdwCWHC((4Tgw8 zruBl7)HXaZUWhhs!L=228b~6+JtyLzF%_grlu~u7%7i8q^$9E$H_FtM9Mrc?9HV>j z3_s)wG9^pt!U+gI^3Ruoz=XL zKS40aoqEDSj%qnRF-y`w!7%~S3-L?IWlHWeRH*+&_ew5L4HqhVXxUH1rF$8%iG<^~ z=22YGi{eMD64_G#waRBB`DIlH$+zi~a>Tq675IsI^;lh&E~K1U3kks^!qI_`4SZr; zA;}2q62n~`W6Y&9)z)m|!pcpzwlV3AB-UWA^v|Kv6pDy1`w5pWom6pVF3i;5-HXLZ z7_s}Adspv$khb@Uy)F^vu2(JBC|4iNt@84M)Fe0Q2mV1X;TUq$iPtbXI@3#$NM)+Z%V;XsWgr$72mR{)v#8xu2XhP{k!^y`}g#Z^p{KOrdI`OauSn= z3N0zB?d>5Dh5dtl=KD}zrWz_p)sXTzIjPf$1q7)3DTMVv5&sv9Z4R!)&~5nc=`WZ2 z%l$+ByZU!)d})ru&=U3b%7B^f^0F83Subiv-byQI)mwACSxLf0UKu}j=%(?h6I0{Q zKXvTX(Njkboj7pv`0a-dxa({#E0iGy2bBgx7*N|L_m>B)!9K})dnPfn4yr+JkhRI% z3q9~U)-&11%4|rHi-x=IkCl~`l}`ATtnMghyQ5m|+>g7gg2UN@H{Wa*B+e=^HmJ~( zEZ1nX4_WISty93@d}QK z>Y>aHLM#i-L(SuH_i;!RGnJYl%cn>%)i~%|%D7}#KcY!hkFd7( z1Jn_ojtH945sU_4Z628;4SvKc2%8Mo=xp39u%YIB={CeSH7F;&;!hU&U6h(tosLP4YR3=p&98Er`GD#Ih5tOtP zwL8W%DA@ls4uT~FSA~H9ijym6#dud|IwZ(dH~kx-I6$%*He#d8+G5SeBrQ*jc}qq! zI{y*$eR2?DE(zvQ10cmclGPz1njA!B+T9S75JX(6l)X=GHmb4x zDvJLQRBiB7p2}eml5`mDl zSt=$km+%z!>`pE!0!0M&$R{&_C^Wp~0wTA;zNnnBQhP{An0WO!Gi`Ilc=`FzNOv^ku%>ZmlT;oM{w$DXII30o+$mvi6P9d0!ikbhty0~7Brhki_ z^4q0Gp0HF9QY8ih zcyi)cs_^yeEG+K|hNaG{B>exoamjQG)kT;Y^=vw!kQq7Zy_nQwvBOa)?_&FjHgqFfbWaQ91pCM!)<9I;w66D#WfM}sun2{UZg!|8a|&Ee zgqU}wQ8%}|VrGcQcJr;?NRnks*zLnST-0cQ7-~i!C^BodC^jl%ai6f<0czI0iXiw* zAF|VHSz7NwqdAIB_7;rDhl-72o>GFc3_t@qr~9R%ljR?xi|Py^4en>|z zEMZX(Oxm3&GIsKwGKN*D4<%qn6MUEt48}Ia7E+S8L)*_vu?=kpOK@4nQW!17VCo_ug=0i1>YA}o6qzAQ`?t-$59;#zp;EsHa@t*5fWNsVI-{99J+1G zSeLP}WrJl0HXh^j%=FAOn&}>Q_lzVPLm(Gf0?sCzkN^pW4TRremq1uZ2yFPnvOowM z!m*Hrg~0A6z@LP3NyrbeZ`qbVptlfxd+PN=81@ zRI$PMFj?hgm6%1!MChAi5h2`1#4Jx-WbE;a20rIU0yj0hknzSiPpVYw?B%ZH0u#ZY zpsY|1UriYjzM1x~eLA0+0yRH=7aYTu82;;P(Vz>`4 z9=&qnOaw941d9~q;kL7C8v-e!0UFS*vI!sndWk1mMJW81J|fT8GN6^lPV1wKmCAXD zMcN-~i|7`^5B!+X=erS;Dp1vqr~%syuyMe+x*EV}VbR*yM&y~fS1C(_#(6-{S>)0a zZIu!?R_0Ij_!~_z4{YL@rJ8&?!Sv^86iSZQA zUXki)mA{J#JPD_yipb|1i+m=jdE&$fMQ}x0$u;SA%V+{30QA94HwOO-^Vd#cB}|{y z((73H#+IEMJnP3(m1fOVz+T!_oT8orqiXSNO3NGWWJ`_Lw;tjk^nt=`t|@xFhuCaU z)tV7DQS2nl&k?=};%teLa!tzyO6lm*Scy)=(0qbkqljgKA}>p0q+DI10tUc4LIVOk zmI%3tW`RXlxK%{U;{13$FycK*c(-m_;gw1lDIb0S@x!;B3j2)$c)#A;#~~nKr<;H%h`3t9=x&eiCMjik}0}e{(>3 z;e54*snT*KI+4l9#&@hB?X{Wp9$~##uwbcqZ)<=BhciH-<#dP&FMlaIKdczz$Vezc zkOu(U5x|2qgR^_6Ryq&Wik&)S8{L66*b3tdjqWgmV-`N>bEPz1ENLlZ!HEhRay?B7IVI6FOC|1z}o3yTkMCe_F)Ic2HNDdQ695dVp zDP@U#xRsK*r$XX2{Wt~ZWIU&_dZV)R9zbtU0;I_4Pp1zbv;Ao7BP|XtYabG`Olbx< zpjhEM7Xypw!9c@wFtX%ZGutI=7gbk-HmgNx>QB>PqPY7})74nC;N1lw4?1)^eb`dX z2}RV)M2uIE`r%`m);}Cfa~fWsZaoY#77_XaD@3pcb#>GFbPM2vg6N;knas<2aaO4{ zCybCQkc#TVQjrczy58hObTHO%aE{55b{H7*?_qqo`WLdFZmO+WdhD)+^p@Z*7U&f2 zbwN;|!l#iJF^HjAo*8v0fwH==)Vw1e+rlc0sTfM>Gb^9?TlKWs&;5FVDOQ@DxL6x_ zSL3&H@y<%@F+h-KQCOSAcFo&@fgT!~O%?}-hDwwHF&ucsZyKiL|L)*GP}-oI8gFU` zypY*m4M2HaR7KT@W$TKI0)V5qInCtoFqoO=Gu{(muN8dD=`P$sOPHH6>3D{}lE6|e zz*JCjso0`NCfPy(_glJ4UouD%sM5taHLzb+lnrGd;%Nj&z;3OMS;`|{S z-Mt_KjVO5$+6d!Xn26b{sV{PI{6{NqpIlJ^4$>6TpU+RscD|&86Thm)yvq|W)*k{T z!Kcyz@FDYq9XBV0Ve&i)`D``JWFWB7`r=8~9LG%P*SDKhU=AUKkX)c1_t-Nl$8u#U z$Q#m3TJ~0tbcxTFa^<>qT+If1`vNX6SXP#q!te-;7y^1Fk7ia0qH0mX_+}Z7TxrEB zxyrakJs85%4ltUh4+v5F1J>m@AU;CQ!?;E#7=H&v+A8i6#1^HSY5AQsjn~sukqp5E zE!)T%W?xfurQ(#5=j$oAuPL@tDd>))W%a(M_)75II@Z_JzEW|FJjQ|PP*9CdZ{B&Q z!!vs>jRai@2^Z4YDwUxZw-Rgvmh<=<3M!3>O_(Qx`B>|a;iNP>4d)e~GXP#l76bh5 z0z?UL?#5ngK$9(~HLMDUx;ha?HIrN(W;p@YCcZkHhQ%!7BmIHNZKeTED$w*Th!%~% z>cXpQp~+^L;WuWKm{_9Eew8QEzMSC+*Vbrh${ks{(#)jmu$I(PB`4e$POOb4dea1p zse-|nR3x4l@Ma;aQ!EX~6TSV3UT;)6=#@j;E4P|6vN^SEA60pi?xYOIv20vEFgb&Xp1A1SN!eCD@2lD?RV^5K zeNruIwhNAR)Qpyrpy=;R40uG&%EFgi6ngAQ4D@?F(l*Bp6U^7JNs1-cGP5PA`Q9EM zC`HX4%j?o8q?vb$x}M6ZNiCnZEE&)7M87l|S5RpGP@>nHZDytwBtfYFxT1iN&gDs! z#;lT;*dQUv@SdeewT@*f9+o5#8TU4L^bQCUi zv^;;EA``kA?NFmJY5w{X0|NrrRVY4Kp=T)3<4sPr3bCl#F7?neEVH)YLaEYxZ#>N2 zIm<`3X66nCb~U=29po(Jv!jF45N=XlkY$u-;Hbs~Dcqspq#+$Im}Z+K8xI3f;%%@NQ(qjF~1#ck5K zK7zsz!VfB>y~v!14wS~K*@Q7{`^L=^l^s+a%i$MSJrpu&9=4grM107i5*9CxaA24P zpNbqugYay#^TQ_k=@K(W7c#$8l+0e}Tu2HDep%-o?|HxP<6U;bOxQ|eBD^%wbjq?* zn_Es>-nwGts=n2yui2hR>^SdJdoI{}A(z>i;8aRF${rp1z9w+p-y z)n$3UbU@7k^?{d^lE6qQr6@YtD;c~w4e4|wzokS}<*^wYeLllTSoD#p@a z2!zfko5Kt}yg%#-LUn@U3g`tLobB~4xdkY))r52y{)Cq2evL6Wk^FFqUB)qv&CjOH z9-k)zSCbb0dS__UDEO4h)2CYeB_bG$t$?=&`LeErwW87H>UlkDYlSw;&icJ}$Q}Cd zUeVXuQa(R9Xql#-f`hy0jq!OuFg~2GcR;T)I%%e8ve1wCzz0IYaaYsA1}gIQW>Sfb zuwp!-jmnYmtU(PT71kKb7SQo+av^{+x8U*yN^4d%$OJ$rrYRoy?WE}zBdNThn=VRA z^hrz_M+jAX`l^H0WC5vgVLFp$DrZ}!vAZG^7p}t!h#8tF2Mgd15)pE-9d0Y)b+;$& z`Chz~Xl^YI;`Pl@Nn!S1RnmpQE-b24X`(RTEO_7nf>;hH@v78YrL?oigM5@oeBSu7 zLM#h6MHP6{WV%I#&Jd`jx!Ykq-Kr!@t_ZaNC~xB;Y5>V%pnj;UkN~hzMgo1N#YV^U zj&bi|><~34b$)~98zeSYjRx~ZN;e&9I<`Yy9nR}zJ&&(tGPX`lj)kta)~rLlqy>5d z>ejAL2~YHN`E3rsO)q7PfZI)$j9MA5woW~sTBfpP>mZ83gX^{^0F1(5MGfFYPnU;s z|AOZ%lr0$p7MWE_;~JxuU@FouESDPVjNhnlSNzqBrDWbnsaiU1>kb(6=g{UBisn;26zwhdE>1EcamlxLC8{7JBUG!1~r z@m>Mu4?}K%#;N8#bX4{*qPsaO?X|(&QLr{}6zrKqxMZgFjA80&L=3WYwy~kQ90o%% z#!@RhQTlSLUAFiN1P?T<~q5D)iGWivg+Q0w=o zLnGoL(j~tb&8pr!M$|4~i9V(tBoB;+x$p_pVHt*T4G-Z$uckC6Bk*kUL zj3vwKzd0-q6c8i!IX~HLmr00P4{*9}o)N(*;TFKYXg*vSBpz3U#{%KNU$XOk%`y$c z*pYzY5=?5YIkY0 zS@Pt0yyV~nizuaqx7qm?k9M1d1A~?iWB3$Q`EbZtg~XvH4-=itjZdXGq9{$wWrlzd zmxd5~J-#BHIvHO{TjM4VAGm8L=14%RMvCC~W@OXX5SkPT50tJbh8 z{MZC}p#(EX+vpU6LoJ8#@B_^woH;pbTqza#Ew5(=8idkgmZQdQP!&}1g`~hse!r4B zp!uV%d_uFa5oWN@?HhP97y|-VhBChM8*Idt3PJE30Hcne0A^(}j_&q}#!|VGIYwO! zw8y)wz+5p|8oNYF>_+Yhzsa54UJe2Z&Kx6>`{f7l_1yji& z9Dq8E(G3iT8%%-27F~zsk-*jxVLT+^0l+R`lm+nQqx1Mfx`e#4W*ZPn%<%*afqZmC zO?fs21WyPw2q5<~PuDLcE^quioQ;>lW}Q<)r}#J5o|iQUch|R_A7+`^lMHLoHcVHL zI9013q&ORNb5mKf)z#rPBQ2t}RD!|gDmcAd$P-iTQ|oa-q}l`xS*G;7s5VZ0oQa*i zz;qYGLKzc$&KyuemGZj1a6ayK5P@2;>aGDLWLP48&ZWOBg7CJ)m=gM@IDNV)shvV zHxS+kxVAv2a+S4t&@>)16`jKYLi(CGX3!J~l>mMCvji$Vxa49g18354^+H5U1F8;c z_C!red3PSyuWSZ3ftt+-fDa26@PLQ2j#3{V>H7zUwB}sS`!t7T1l3Q!AvjvV(D5_vv58flu}xLMlmhup$c6maoc)4)54Ksqou*V z!XxHLu`6Wl9+U(l5bxb9o?fKV?BOXSQ**t3Df9)D4pW(J;rz<88m9%y4uD5((X}-7 z;0SU8xU^(~NT3Mpubw)On+!KIcFiXZ2YIEBI@1J4m#|-f_yGny zT3#8~F*XWT@<|q8i-yo~Z5opGFm<}j6l{S55I&-%%#!ami2eZT(|UOT6smk`5+;9S z%x;j#9^O#_GEhQt_R|+y{5gr4HW%GZ6(D*)$4p-96tFjh4KW1@VsJmqD`gyyu z;(RNKHVr#?oR_5vXf<63{9Q_=bjQh*@(P?;(1{l$D2B^?3jy&X z(`M8lri3eZ!PJTon+oIN&>sm3L2Q|0fKou4fkiJwHK_lL-Fgo3dGb}A>gL7#Ni z7mAkc){`mX5<=YetAnHEb^s(m-|*Qvcdmh-3+AToSC7sg|e{qAXqFk4Fzg z$S0nmVg-bA^Z@~dD1YG`Wrae)QyeF!jOmlqO9s_l!@m`+1i__TBZa1A(7>QooV1N> z&Q+RIElNBZ?NsB@c$e}C2sopx!niYQc=Vao3+FF|N)-W+Tlo|CzV5bIFP37gi7g5) z|IB>d2N;5wUlb{4#t^`2JV+iMvk+<-I33jF8kX%521ZG$%0lQt9$AR*kvE+lT+H$+ zKsLh}-stE$kFY@eVnV7fU8r`KDh5)Z0#=oI9cQ(uIS~9(a})b{?Yp3&cQ@a`_W84rw*5BAuqHXCsz46J58YHlYntIgPqK0+>-=gn8yCR|GX6 zMap;dT$o4yt1LdUqS@IJ95S1omR6-m!?giY>6$UqO3Be}@8|^7SF%k()c$)XF8@NE z3YnL~H&Y04IMk#be^z<1GgCDPbzg$UPifuJZ9~h0<^$1~*7HUIoagjGKq?HPk#@?8 zRRn+f4*YH_<~73vg#&;70aMY~%)FwgtD~USbDW&2r{kTSv0m!8ly)lR+K%Rr*y|mG zeN!_!x(>0=eL7Mcc+DXqm=9B@R0O81r)P?awT7A1?X%#ZIWp7Igyb;e@(xTuC{BS8Z>aQVMzN#^T<%= z3Y6|DMj&7aw*daRmqe|s8F^4K;HeN`4wCJmCx;@0U8}JB7>*H@vOSQ$eYPV(&7zNp zBwv~Af<-wMU3dnYJ(WonhhF29A$s>O)xnIw^Z@=2@)`@Mp{-crR0&vJD@*xj1^-uql*hIgcHs@<06nDyk4KN#q|97B$E;Ki(bE-# zg+#@dG2G>ZTj?=^r$xOqkJM_DW4L7o1n2Vr8=QN*1@Vr4<;m__eJAr zowlRXx+Q(og@>Jf!AM;lhJ6B_=uwFrS0{W>RU%+{Kfp2(-|GnDkp*NNc{}pS0v}MI zL{y59wjgzIel}w!{XummpsY~e*8%?sLI{=g)x4E8Ou{~MX}X&#@{|ThDI}eoX6p`5 ztfz@Ek^VF$r8W^lLWGcS!XHA&EJDaN@P`mmM+mu|r9U+X%8bO1B2x{axrEe1%kv0n znAJc?LkN^7q4|U~wvVpsk9T&hn9Ox;OK#{rbN!}WL%rv$(|Xr#jGo!sea6P2LS|#! z%}s34d&i>fBgN7FzS*Esu^kO170_HnW3gBrA&qlTX%QkM25?1>16bw(Xsw17CY<@zafavIjoj`pISA+Pd=AORmh!4gLDg*N=QDa?v;bcH71q zciwvD_zT6@1NB$G`q%@1cm5ZC@cbP;UwPu(yX(*W@i)HvH}~CLFrGiH``iDsM)`Eh zwd)>v{L0IZ{^{l8t)Khj9sBmy^*sGQUpl5e{O=F6j?A4>%ni5Nzdz7%{Mom}yP9wL zM!Kb|WBK>CM{~wcp1b1V2RCkd@z~2U-_$nFy5RNw0}Yq%Bg-!PS6uv0ANkwg-MBAy?%o@&nI%um5;`$; zVq#{=6Laq9#87Ehuc2plrPdC1Y|Kxdvt@GA)@^4O%E{&1lI7SryJH*9I=fh0e|D9L ziAOtNV(ODxYOGY$ZEtRXW-8`pR*1a*-U0KgcP+pFz4cc#J^9u8-+m#yck_>q9{%%n zrxsuS;pcWddTsc~Q}_IK=^Oi2mB07u5hot|%B^P=mfioYo4Y^%)^$I>bbsjdh65kT zsq{<_=Fe7Aq|w?;mG%_ldR@7(m}jm}%QeU7|5>&3@!nEmzg{`U$mJhb$&xg|HI z@BWA3Z~WH{x#;;8-Tl?9m`$JpoA71r~t*`FBV#l?qCx7(zQ@2M_5;uS)kAk4z3)G6-umUy1DF5v^F3pmjRX6?Iq=4L>wa%@<#MvHbKsJ6aYk-qn@%ynV^dcy$bGKu>eufoTs2tt%inzO%i}+P?HP0a z?RP~lB@1po=fQgq%qjlvj`i)2pLfO8KUe?b$+|^fxMgm8ds@ZGp_^Ph%6VZkzG;kc%EmZ)U0mmw&q%PpnkY&8E~SiyQ-@f zih0fT_Pu3QOWWFb%^DmA9|(?X>smp;d0f?2L2)ID2n-l0m0hfJ48T@ia*`EDgFPBH z=!m9iPzF9R={rV7;&TYOl6Q&Tvf25+Vn5G@efx<5DXy&*S6c z5ywi6IT1e%fQT|a9#{2(RN*M8+X&=3uI`Z+I+ zQz+ZKK}f@rhX|=ZFq@E{5mNu`9728$*^j`Ve-gdQ;QW(?_!3qnJJtuOsB95SdR#;>z??eJB(P%_3w!(h!WA4sQ;b0{Eu^ z!g5@m6D9mjmon)jZ`z+zsF`Ee z%z-iR)=uz20y(Olg$E|8tBJ*TQe`2-WTiku%^Uk@WjWrMTnwh&Lk{*?&{8VsywkiX zKZdZ3W$JOu)Om>$D_bermTURjfraMv<>a)Yw>JH7!1SqxW99K;lK0|=1Iy%f4IE$d z68;{FR^CWW@;pvglnh+EWRCGHpmPr}tmZ*hrPn|S|GcqG6$q^g5$&>qoQwkoIYrw7 z^$`aQI2Hf~SyEekm@F9=0iHbf=pP9#?Bi!jKfn?tQSo@#ktFvvnN?-Vq+Kjo>=L((?VSzX#(0Dm-5 zE#$og3G9U@J9aU+&j+*9RzWkoWy;RpDN9TsOfHxNX=WM>#Xz+z7Bvi`Xn{)}%hhcO zHaK6G9Kn|WRG815$&%}OO+#n?6d3+^(Fv4;;X9K~Tumo!!3A)G9`~og!b#^+#fS~2 zGhMb-lH?|kaKsebTH3HG#skEf(u#onR8BJ;JF%*H*MV;%6%!6;uF3bh3Lf$Y-6ZKFCG!M{6V>oT4#&o;Qup*OI z$+pHKu4UVFmtKK_rF$eHjVF|xWDH~)Iz%VpI_ik#+QzxZ6Vlj}PIbgG9o?O(-lIj; zj#y_}O~#{fwWGZ|*45G3-QE>#haL9Ft(I+%qD0NASKVvpA*Oj}U|{P+*@nN8p&W2@ zI{OW{TEl+NCWN%J-@hk>tfbp`18npSv%s)rLBuM$5!Z?2tt{BIEZ91_bK~YScAnM0 zbsfM6SVO2zXH{oG)jFuUh*zb;9n?Nz>*&tG&70O%R$s%a*Fp8!Xi~$g1B&5RjCa3v z^Oh|;ht_ZLb>GhF&*t+CP0a3z_C}%Fyse`<&)U3YtFMZm3=7~dSs-qMggA~YK-@-_ zE=y1^5kfZj5ce=>s)FGEjF84-BS;wxrF>uj)ol0&B9dc*A`+UC=Kxw+;%g;uWpP+} zD~t6vN|;1p4Vnnd1+;RsuN68+*ib5i4Z+M-h;@FP(Mo)y7-G1A?;$c0Zx4}BJVY8v z4E{vnPb5Sd>k$QRq1YB8jf>$WlCvTb$>vh9tke)r3w{`c|CDCZApi$$-JNF*T|* zr%Fh5`AMaihjT?*nOHZtURh^3F6y+w1C?&KDn;8W8)@B90zI_=E7LCpUw$;%S1wOTSB9}7MTq@lbZG*iW*w!)CK%WH}8-d3u zoo!uh?Fz3Lg4SYcbX`?6#;c=oRwWwa9}tb$6Gh{P)0BtC_6jt%Gc?Zbj7C39JjT^% zxGElj9OHr*4f$J#ZVUQ?ul{A zi}@(;n2y2D_ExxD@VzF4Xr?WE($A+ zM)Yz~NNmtFNYG}wXj>DL;v@@ltW>3x%ocs!z{vt7s$vl(I>)uOq6$_M95@izOwBD8 z#JEA6%-UKJqB%qyxN3`lpFv)sN;c@Tcs2~y)ZKB-P33qRK#4LO6;UEKHS_9%QN1}m zJFB7o{AJ5armNge4DtB0SDjr;a)X;DO@N`UpgDP`dr4zFD8V5ZSE|xfQ%bv z(wb1)+dA4Ci3=xqC)-RDTUJoRRiWAK?STfkR0tBz96}J=AYTGR04fN_AW6?5)1i4} zx_%LvA`8fL{nT^=`6!ug2rVJg4YTHw>4w=ylW91?vd{GN{EvS;IiF0kYp4GOW+s#M literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302200004-Config.rsc b/MikroMaster/20260302/20260302200004-Config.rsc new file mode 100644 index 0000000..c6ea9c5 --- /dev/null +++ b/MikroMaster/20260302/20260302200004-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 20:00:05 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302202004-Binary.backup b/MikroMaster/20260302/20260302202004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..a30623e263f87617db68aec247e6c08eb4fcedbf GIT binary patch literal 289700 zcmeFa2Uru`voL;AfFyt*ARxXX%`UK;o`?kz5D`Sch6PhL5GlbVG#i4VSg~P6#g1ab zUJ(oS-W3JK-h06U|7SJ{V)y;7zkBch``m|T_hi|#J2Piy&di+Iovc+03zx*ukugF@ znUJ7T#hM|6CQq%%SKH|C0Y@7Y#HOGs2AnrSRr+oSsa0{R_ym<&Yj`lO?*vC21+nP}*)*>Wc@_pi@<~2|P&8G~`nhiLtSK zT?dj&Y9KR$4p(I)A2D2VYxOafN@OvK2{0%cLLC>S9-zn4U4N|2zCfKQ{dwR*LmPTW z>dyn``Rm&ZgixHm%|r;L>f41>gxpaO+ZdsI1Z)E6>1YVgVA_#*0ZPVNA~v4Tg3Ns9 zVjwuPUd_ccg*G8de}*4s1yh2 z=mj?bSZK+~$(E>!JpR^WfJQ%k3?1NF!}#hk8cj6$7>y=6vIcLxJn0BUj;jd(`y&L5 z;m)R=$U6gJk+Vs1a=SHxhz z?PX41-rhJ_8820(0MPno>c4u}uPMcZ$JYM}D-%hAvW8gtHVgEYQcc7X8jUO()X?wf zE)aoOnOv(%)b)YQPcH^=^g}`Hc!Vf}KmZXb3`mI(iUFO65R*b6#9){pq<|k$uv5V< z0d@mHwcumH2r&iqu9k8$9t#I#6_|O@Rw?LI}6i+Pb;k-f=!JsJf}BpV4iSU5zC2 zIAwf#4O}q4=wZ_hDhZnoCX3H7f#B+3LL>mzuUd+lSi2p}cHcBKg3)Z*Lo3!)pO)J! zw)f|BKEUrI(E;FGQF42rnK-@8_2V;J*I6(L(I839@0Huz2 zy?4dNmY(Ma6byQdo?+#q_I3@a@NyXFvAM*grT8j^9G~zp@;Qflo|zl^bU@;vD&boI zh#9AhQL7@Qk{IA{gIxTsRKRtyggjEKRz^h;>Y9EqNx%k2CJJI(fn{U?vxr2dC1Tw* zgjTDJk0P&!4enz&n(2%HMqPxcrnO*_{l1|AbC+7BiBri5xHC+Bx%wx-F&71~jS$K= zLbfP~ZGsSK*dT;R)ddEQVa`FwoYa=p)zv0nUdtvmb9HsKvEf>V0@s~W;Kqh)^|}%) z7RKp!LOC$I5e1><_N1JWlF*2hRFc!`GQH{`grre2RlLG8iijuF64JVYZJ-_lI1bd! ziKMmxlLjVkKpHGHpgCwDpq(W`6f1;~1>D~pA;$Y^AV(EBJ(EAkN!Jb`XBY!#M9wOD z@h8~}=ohWhY7$gh&p3%P-Y`;MkMLoHnC39ThKn`oqy)7}VYq&U9(p*gKtb#|2vL#{ zLK6`}lMtee0|>KWHyI(Obu_f5!)~TtZ_WZ4=tj{&KO6p|hBL2dXfRCqBjL;_*k!_Q z4D7}OMxzmOHdn+-G|`@V(5AuZsj!;@yRop#f?X=?YEz&#^2t%k1o-_slSOSh01=e2 zBp<@|Ku-raK0rb2`lJT|6GJa5LiPydQIS20)@l>Po}S6c$sVM9YLzh_GF6;sgWCU5 zs}i+@TB?$$<>WsdNy|ACA;1|ZfEwtOEvSB&e<%usDD@DcI3UFIa?+E}8A#;hGGpn8@SrQG)x`GSOKZ(>ga`>f&ZL=5uJ6cWD70QSkbdmZ9>ANV&IC) zdTPM&vfe^A*cnE8XTuRdBfTmBL^u8<*V>c(t=nvCwe4!P>(y#I*J?Y}YB#FY2A+47 zsS@M0gj(YyiI+RYD&v$|jgvy9cG9Yql2~$5)R+T?rU>C6c{%}fhFMyNwz(c{cd`eF zbX-EL##5n;)eAJ0_>D|vL)Q@gfrr_&0zNRy$; zne;)G2^vD?35vAVeOl@71IJeS`+&9~jR}%6;QEr1WTqwtB@!B~yDC056$qibp;Au7 zYn9s6-z9`~P0s{^P)8=HRS7DMPBj9mVS0ez7*@kZh%~Zck|z}hX=s3*ox%hy%+j+L z0L`Kx#599Bl?s}g-X1uj%GtoZ@CY5;@buq>8Lrd!QpGA|srCpV@Lf9Ufvr7`y%0hj zQ4rf;wUKTVISvf~C~y%#sgT^Sx8rrA#YCT->ni8(dEFqYU%(MbI?MnaSe5nl(7>_2 zo^(JGYHb31Mnxl0#w%3t8#bR>N1x9OMS@QS@J9gAg#bQjX_EdM=sHq<$@!(WmiRo% zpd%u`HWFIvp9aU)x(Sd(0VY5o7!#f|f}tN*a0FpANx#q;<}1CLf|(1VGM@58rQCoC z3=V8?wAbC+8Ghp|L_?HL*%1R4vH(1?qbycQ#A_o}30kEpUgL%kdR1Lr-Bx!8^t!sb zTBvWosjjYO>)ZJVp|+nX%z!??cWppzSYas&g17NOulu{lE zzzS>ihNsl@u8XB$cunshZy&NV!_b*ss~+0KE$ny}KLRl0tU|>$RSdNaYnkZQ}_+?~> znMJZ39i?=`FYMWQs|JTh~T5mXK%&8;b6^FZK9=e7w-NKOltO=-X^6LihD;9u=WV zeVb4He7%5*&|Cfa)>MRE>)Y*Woeu~16%18`PDCAi5bS${eOqHL78k*Q#qto%pU2h2XoR0#5s7M}+EtRQe}g2Dn5KF`syzzeys zn+rQq{S1ZH5QLnqaWPjY7AnL%iC9R82|_Fp%As$k?1)KE@?ZQ>lw*F5a{X^m9)wC{ zzeKqQIJ!Im_PZ!s;bH|QmJ?zHE*9Zpxfmx%jGvV~pJML#=8s|=_H&Fse1maCsa*Lh zjLkZPM*6EXT4lT>Rq`*e#>7HQED(qZnV8EF3;870XhiZOpV9aASW`(A2FmVFu(;pX z*fS{x{$_vz`3C#4N3vgH&kPO;z`cb+VaMM^9qABtG>%=HglL`wis38fR8`*RW0j9lV`>A8#uXZ=qO*i-owDCld1%I=km=KBOm{`u!ppobOB+(MF5_j+Te=~h42r*mCV~eGPn4=Kmy6LNm8d}uO z_R}Bb`My7=1DL7b(4pn7C%+VRi;liwf#F?4+l>6Cjcxl&X*cQ`6db_*U5u@9F~Jq%LNQ+|<_X0du2`ZQ zf{kH>LPD_RI3fLQUbn)< zn3ydP<2w32(h#U^Ox*y6q~F} z_-(zWv&;8q+@J+m{#hj!@biI&0Kqr-4GjIY)xsccmS7_JU$8fh>CF})8_YF@-b58P z%1D1vU(eqEm62sQQ}RaE4lG0h^03s-2spG-5d~0lAC-i!Bg>F3`u4;aGrz*t&&lTZAZf2$Ac* z4RqN{-9tN!C>C$as!5UTw^!Yp1`d}1J_(Gu#8oqR&bSn=0LL6U}&OrV9$QI8ZH z9Z?V)(zGBw%hCdo>x+z56ms>1NhW60T1Nt^K=R2&{SDxFk<6Ka++tX-fwi7`2<20d z2?}D{0tODXQgdOIxDG4JMKMNIHPE?Am$gYFm#GMCG@-_w+?~3| z6Iw?gASo%2tV?HP46v?=w!=zGj8ZOB#cS27SWh{Tq?8eQw8>>WS*$9tW=*cI{y%W+ zi-N#j03M}ib;}A&SW{q9vh-uQQh&?O$#x}yc}Il z9jp?SN&_F6Hgcw*01PKjHxLC)>F!s*ozKLp80^u2?(#TZF zuwn@u04Y4Cx|I)-bs?3i6+(=2g-eyNKp(4$a+k=+RZB=lhYeCiU;}tY>Dz#-p$%+o zxCYocPk+ruDx4?NwMi^l2tf`2fIud1gRsEL`#qXYT7ktGkkw}n99l;|Smc^E2rd;e zO?0^(unZ56CA*T#ww7RQ=~8%NRZ%s|#>R0(oJyTK>OTPmnUPHS9VqB>r6%S-0t1-? zNhTx!5r0MrIw6Zz{YOTF%zUK%4jqiuM4U=X`?>X7zkdvfogPW%D87!h$2Wi0Tpj8Ml-*7GsQ8EhaA@_M><8-&mm zkQao|4M-``C%eHqZyKc8>GQbm>lMXAgwP!Q^-mE(5`9w8GlbAbP#F64;!1rR)`A;@ z)jkkVA(Tf$bmY^fdzc04+NKMkZK`qd zjhCrY6ST(2C%8>0&K^b15Ri|P1_A{un@(~8&c|e2wwx`;$$T+oe3UktAl0l#JfVdQ z9y5d>2N6^w#TX&Ry2@rs6NDIR^A;#4BE)$1&~`mcA|Syqqk1JG#Oyr;A%+n`#f?D+ z!)!op39U?o7&?n(hV1BUeLTEKkgbrR@z~{0>d>#+CKnTmHkNjjlJ@%DZ{`gZ$ zysBqzR(X}{DOtKppr!oj5o3x&(H;rq*xK-ytLwMC-_@pJdr`*y9w*GQFHS|dg$EsX zuRcaRZU_oh$)t>aYwvVOR9twr+vBBc$(ie_dBxJJvk#8A;8WiJoy=M~ z&GHnt&c`^ppIL5o_u|71qGxtqven0*uXgWo{*1bv`|0#K_xmree{uVL7y6QOo$ZU- zPwNx&@>=@4`#z4{cKk!Njg2Vj#_s6ha4bR`GK(K``{D7*JN-*nxDQu46+c|E^h|T3 z&?0QR&$O~D-9D6FZyVZI9KI88HSePM;o=mBvCU)NpPr~$zvs!KQ$}X~=E6^^W-eXc z20V{=_v+aW5#vLriokX&G0m9+TAS{U69=tw-F7s~*t`_U;16&;|=k%Cbt$CZ)A=~l#y`g8PZuDij2XweNk)NYH zZn*mQ*WIdIx?J=J!?t))FbOOYa1SBgqGdOoXOvjBfB)mV(sRD z)5BV|z3h-MeL&ALe(JKR4f-y!I^(>u?tH6d!Br#bci+2pQ{{8Jl_}l>|2g*7dFPV z-H2x930G`iX|9})a=bhSA7xw++NPcb5jK~JXS0@4PwwmLmZZ&CF!b)imwUPl_WLJn zThl9#*S<~L@Z$WMJ4;J8WS(6rUT4uJhx@|oNtY0Dft$?cX76($fmLJYPdcDnd<+_KYiQWn}rOz(HkbAC#r)WS%aa_q_2 z_sohR*Y}=nE9*Ao;BBeH)y;2QC$;k0y2q!afWuq(vc&>3)$|YJ_6fpi3Ag)&){EFS zea@uj2RhZCza-YZeP$9b34c6{*T{^ixuShwax?kmxP z7PBAp9k}sUXzUKNw6(3qynMXk;`Ieg`k<8MXwZ-y(;O(aca5E0MteRlpI;F_kMfa0 zoz%8*_sKc*Th}_ih&rq}n=>Y(yws)7#kPIA*+llMc})5ilh>-x7U6-h zC!XA@pL|uUFuteF*fel@KlO{vN%<3J(V0uV1^ud-A4PjNPZ8B?n=Cf7X*OeM$(Xmp zU)T*DJIlMGZ26vhd39ekdLHC4WTdIUg!`U<$alp2OZ20}@@M&Rv#B%+qAbp!vat-R z2Uf?J*1e$xg;GtY)2K#ySVQ>Tm=5E{XlYC_GBTl2YFbpx4E}8mms2sMySNVBmTqG^ zHM4Wv*!E#@He2RDn`FP&`gzDftPx!7O1H;sN7$fE&0n}rQsMXJc3GX$_WjlSW~a|! z9K)R{6nayvG3ILcjZsJ2>660MINL+%5eu`ahe{pgiM52g)}^~)E*ZaO25Y$3iEf6m zFov;lRJs|3O2ItgWFvYrtO@3p=aT0%+OgKNWVN1!V;m2eIu^^I7#Xu#8dK<$3#n8( zm7e~Fp8gU&M@gvu=yL~~tyEQQr>Rm}1W~4}JmId!E!Ldqm*DN*xXZzF2vO!7>Uhr$ zAvz8DW4=^pbU0|-%2Fn$-<|U2A-fY+j^5nT_;NR?Gst$FDnFUU_z5-FEiLS$D3ZWOP*cw%*vGqZW3I?6c?Ehr{tN=JY=9 z&r%v?t~+Y8&!*R1{d0xnb30*vRA;n%_e9V7mm5;gJ#AhzdLPrF;e2IB)|7_}THI~c zLg{foo$8EEFk8mV9gnRT*EIT2N%K8b35Bnm?|$gfy2tfKyJpFkR@Rm)Q&O%dNS2s8 zZNz~A(KB)m?xR+gpFC^c;QjLQiV``vJY=L!1b}LJxF&2+c(XUsl9Ip9f7>T1iEEq57hQJr}{vUlSB6Li`e>4Uv3Jm;1ki*pw2i8_nV<~Uts+juvj%!utXYqN2q zCfPG$U*xTAnJ9a=a^tG>hC#iAORw#ToM*2*e`osSb{|_lojfIHrvI7OS!ZVVST~?v z^!?_0QQGN}t3Bd{$w$P#QvuxYapvIKh)+UbAw=U@H#SAYK1pMUk|PxWW^U$6MDSNzv2{_7S0 z|H3PtfRJ;0j)*Ol5i+4nPH==6pG)v%1P>?pauFYwVIqY@CK3wyBB4-%38gYzA(SZi z0x4f0<;wXYOraQu5dK|{X*~Snd!AAXLe6d&PcG*vgbGX{U}JJNE+<5C5s%N4^JSPs z!o>w5fb5s#h`5K*ljJv{~@ss;O#R@RQFwn;>Y;YUaC zA__zDyFt~)wS%foN&q*GkSirx0+0M6#)?A_9%Di1!Whe-KGB6P>Y}|??7)N-8>bAq z+Wu`tW)rWkoEfa^myrv7#DQh)^efWf^+-39PO~hdR6P|jup296AM~dr9ECwV-M%gd~^@bUTQtjbhd}%aZ0x~ zU2ZpvXLiR|E_Lare&uemH>kZ=ImLBbir}>a!RFo>J!l^N=_p2@T~vqJ50_EU9L?mo z>_sMdr)HkL;wwq#wXvz(UmQ8`s_6`ebqj8`c(AL*g;@vZ4k~D^weTukKcFZgFxdWn zX$wu?u@Yi_)nl(^M}t+j=2s%W4b}C7TF5p`QXH_)OgI=qs9I}pcN%HI=+)2Nbzc9) zRrgBK!ZWXK)(?8|Wbm7&^KT!|bzk%%E!S@KQ)_|f^u|N2yf2I{zW>PiUGD~I+r&c` z^rg&`()Tvo#aiuk#PU%CU34S;9hUz3%h(2G^!H*LR71ppM!~EgEI`IK7??4IQcb1Q zj&OWWEWe0wq;BkeXUOK;w&nO&t$qCcUaR zY65k4(!&kUD=Onh<@cC!V`|{r8xK%Qr|iV3H*fh3X)vIr)7rcfHn)Av2VM^yz2xN; z8=Dm?BA>_kRfdMxwZDJMaoC-Dy{cA>|M>LveA#tH#lGa$jVNQ9On=EJ4Y~KAda=5mA2_wR+Yv0qO=I#Gf+PmyYYP@Su z&Wow%W;Gw!_aSvphiC6z2g{v?k@m5XK-<)27Vud8-FIu}N}Jf_PQja-zDzs5PdYyOVDhUp(+>xFzosby zmxatd^>pb+>c#;iUBgMc4fpW!D4Cwr$;f(6)%L zY&SYOP@8T&Hl$?WVCt%pPD|?y>nFK&{Inu3@t{%vdt*1r>bvd;**N*p-b6v$#AOXe zHg1NTgNx6KkLEro&VC!Yrkkywp zq5x%V2vLB7HiRht>dC))@{1VoUp@I(PyRouC$k}6iL~%>4z7?90)dc=;e4S;B;iRg zjE!+5B0?b(VhUVHNTqTCk0-kZ~-otaWRE}U<-L{K1T-DJuH~1ASLRH1vN-pq;?MrW9lq>x;}fN z4(i&bqcTeAL#VY*0r4_x)U|sX_{@%68KsmFYAt+8#{o?HnydU{RZ>Z;&dT@k{=&*P z_gopWDBCo7^5I2GpIDuk(TBoxI!2kcJQ&*&_SR>=67`%{ zG12AP7~}RRoq6I!gOR(-kGCG=S8+jc&}c(aQ`_tz^Br@BJ=xM}G2_aGwS&z>#zb1@ zevNk8y(=hs((Ix(ZE(u$-kH(yeO=jsyMv4GMa11q*qv;-`y=H|=H>j3mc7_367A2Q zUR2~?(RAReIh=O^i~-}%MQ#+2+P!dP=PtwAp6nVKo76uqP%vfwRhK()Cu|%h4Ln+P ze1nbL?qHwh^Vz#!Jb8cCw8OcAE#B-aX6K&1OFzG3Vy||a8r%zLwkY8WPQUhcz3q!G ztYDM;$DP~s-;}m^^1iiAb$)>ilYBGVS=5;QMi`AksjjuENh=HC^*G&ShvM1diUtk# z&0OE+boVc8{_kE;Yen2hzesj8SFo~^wH53AwT`)6L)X13UqgSLn#x%0X8$p;<)~u! zZRZbGz1q{L*U_zUxr4QLXEiUVyXj^^-ooQuvSv@4FeRa)z~Y~xX)CH_=Wm$|IJD*$slG4?^d?oBiO!^=Akt3q@ea`hc?Y}uc)NSEy#*cpI30PuzWg8B zNlXTO6N~~DQreoTwAvQZeXx*hB{~Z!?pq7#JDH_+KX`nNbz}zC5d+JhJkwc642zaY ziFMZxT~d2if;=sk8nediM>hqtMu1^Brn75sFl&Sujtemk&cy@~zjcpasj)Q^4sVxq z77cyddrzy;+~-X`G1i>zH6`Q8>uA^cudauz^pEb9eYbqwr-TOwSDv=oTWOjXUFgAj z(ZOb6`-we8QP);xv<#0s$r$5#xgvax(UtC5ANDnrw?7totKV6^W_SFVo@`tB7|DaJ zyULl$`Bwvky9S;KIJTa-bncn^F~b*by>_xo4|ng3SK83*0h0CY#!oMu7ctLq%gm)W zFTcFm_uT1613p+f6<1i*$=MRzuIT+G*M@Q1Dtj(ivVu8e_o+n(jbC4B;?{Rup9xE% zHqG7IJag3kJ$+AI3M!qPYR;*PrYf5!W1m7BtQo!N#F`~dkNLigv5Lr;+*{N7U@9%( z$Wq5WQ&l>bA zeEG0M#%j&HLbrFGajN;2M$LxCz3$sGM07sW^HV_Koy99791GUJ*u>)mUUl|aGN{|S zwbE6y(;i)!zT-v|8a4fjY0iMsx0|pL&VH-Iw|4LpymvoUukjv5Si!pK8~L7jCTrI{ z^jLwtdu!}%_uOWktK*Qfp?<`t$bpSs&3fT`+q+}NC)q{chxs3Dvv23Dc;(u}zxZ++ z+48)I0N;SXO*a%+WLB5M({f*3Pq^7z~^WqbSikEzSV2fLKUEKUhZIg{^} z(D>eXS1>z3>I`Ow{)1p-Zq8px`70@8%IaT9xi{YR^L)w7|!F$WkQ@_^9hW{W^*|*2`1(9IT8uMA$SA_Bj@w)DJYoF;iYqDOH9F* z3itvZj!W4BnS@Ku)jyco?pyxr>9=Mv(j8ud{NeQbp!W1@{#(1+PM2or%>Z@LyeiD6KeUjoBJXL z<#(C9Z-r?cw}_A{+nQawaH8Ssc5U~~9Pv+`)GYg#D>v4uSl}JdWNyZ;bk@0<`T1`m z*L$7HweyTvlvPj2pp6|ODmhlS`tC%za=r737K?&sh<6_;Ym|9>q~E^I6~p(gX?ymO zXV*64&g^8Ea1pvd!xTPmUu4(W*!@trV?npr3-q`dH^x&}Zn=CUA++_JhN^-+%`X{e z7DdZ%wxX1e-@9sIhP)`BgBgEXyGKB{K5S$$tmoh&`3ud}BN@jsPCN|>?%S_!!wI1| zYi4Z?nUol;nm+#hu*Qd%&GcC8{g1Wz3|UEQGw!TKrc%yQx5}2?U(dQYg=wB?6>&c- zabQHZk%eoo)bUFl_+ZV*Y3uU$vyPZde7M3XqiO4LeMcRh;&b(%M3=S$x0KZ(#7!U9 zxjWar{+wjiKb4JFk2_(HBcFO%shIiax zen`5Fe`}bj{mbZK4v`7LlkavDj?F8*Im776#8QDt++~-Z-8VGbMNcT2TyIO)l|3X~ z*BP&ob{%|j!|gQ=skuRkc~e-}ru4aZml2C38@8+Kl%GiIo85P0=gaT9ZMJY3CO)c| zZ_*Y^S)15>{R(BbN3I^iKHe@L-gcfh<&}C)o8H$-sEleUh#cp!@F65V3j z;hDE2i<%!@T5)He*S+1Ef+f#d-Wsm`P%<1{bCp-lNp~~uJotIzrmyD|uF?)J4KIwJ zdF+{dmvMIACdD4hpKynZn@HZN~4_q>^qLVGCcAEZ#$lQKk~^L+vRS@mt9y|CuqWitiDMaoO$+o>EV!I zCH38$%H*TLZM&^d&J0|CxXBJDlLZ3~kM#2TB(3b6F>0NZ6=O6-vUh)1Tdy0VCS~nf zuxxoV>x7~Erp0`ES-QHk+pMQ|8P<a;GpO^W z@K13WlH(0uHpvT4>lm1`!3%fWTEV@w>1o)SI&D`z9a5CkZ7v!*=Tw6pXCnI8Dcen2 z@_J(U_N_&kYi2(eWvo88J#eqtKb(qzp?BA|PFa7x#r{>L4FlR`Z~ZiO&lg zD@i8*fXPPGp$pPZD;d6VS;26J76C6^_T-i=8FMZ}K& zS9aEKAJ{a$i^*a0mCI=jXR!PhZ`jq#A!D6PcqQ*~CC-*)ydYo07j zapksc{!Wcu_LY~@8wy@6IEF@!xRo6@BjoDBD8D6+85fdG3yujMH3~}(EQ_6RA^nq2 ztLk@dT=tmArwv>!(&w+Z#t*)A&Gq%3C2jd_LWl3p`4}N@ydZAq36iZB=jr$@wbfoUpWX33}IE8**B{5 zm!823XQP#AtP+3CIK@5ZgsJ=It$Skp&UkpjxCgUkclLVQN8T-*e(u&d`xdmsiwRu>`xghMu}2c7-MX}^`)EtrA$nGeo(U=3 zd)e3fy^va!NsHzdf9h4Wx7$qGy(8m`uST^VIuK1RzZUM#f8u$_bdC2R>t*W&^Krc;c%<^GOt39H{kwsOsRlG-WP(eu)# z4$pnPA_udYO8lP=(Rl`;Sjd--0DWC8N1$X+>XL3(2D;BblyhNDuZx2kWDO8~5up6u zMEuoAllD)@aFZR_`q6g%8&7oBh%YCUolbz`7(0GX(5fop0nOgx0hh)?d53lKX7l)LjE(tt zx(GCGdYu?+elEQ7XApV49VdY5s_9@JNZw}!NGJ@!oT)$IEpPp9zLy^)S%9DVAx zE~5kEutkR4?cTqYRKme zyDr-yQ$3y>+M^_{>5#!zJ;ptMRe9m=jqF`H1uq78*Gnk1LhqZhHuV(t8MeOLv_Uy_ z26|8L!)x$<$om~7MQ&JCkEi=z4x4$?=Cw`G(dCveY#$W3Ji}e;N|ckEY)`p7v(e3A zih{(BIhsSOs-N~_jqB}mW7T@G#mi0~FUAP=$gY<8T`2Xf8s_?G^1W^*j@=eVJ`V5; zPivJ`^2$1QW<4+3y@jHyN;CGJwYELGO!x0FbkU*QVRz02g|F=}JAV&-Z*uO1PPb0f zz20KP>}Ng+C)*{(obD1(;MRYydB!Kd{DRnN$E2Yh5~seK^S*!o_3I?J8#UUN#+-Gp z&HIsQ{>p_qzbJ!}fn`vJ{~~Eyn>nIbaj;xac5+v9!Ae@gqQ}SWzVMHNUBaF0bMD-X zzhm+K{Whz|#&+4FFa53W=R?+hCqBuL(@mk!2V&8fo8dP`8Evo6@m9$+311{#VeMrx|HzNmuYv7Fz!M=aI`?%_n| zV_eMCm^ol{C(7tgu~Z6XVr&F2%TsE-HE(!-o?6qQeI=NrCpr0f!qH|kl{1HGKNY`k zG9;{E^>O0U_FUuKaTgaps9?sOj-UK$+j~!nO-bJ#a?0glWAcSz3&!{Ji|c!!>8SK` z!zWBwJU8_2fviV@p)Ec<>mDIgTV6ueC%b4$R|3ruE_$<`J) zlq4kI2L~lDau#n(nWr^Zcvn{x8sUpVtg!LX6E*h!iqDPa#*xL_8@+CK1YH z0wG@@6-jtPft1G<2t)#oh$j%?0xqAUkO^^)9Fy|dJc)?3tG_o_lXms@=4f3GkW2v< zJfAJ)@iDf7E09QqJd7=4b7V3F#wTBf{1=wjk1~KH#(y-a+Mn~oWTBd*>f)gH-M}($ z&-(x=L%L5zJ_WPRH0LwVii$KZIsF`V zavzi(n7i{-&YNe)PML0(^y%g|e7^gFCzE7mc8^RFUY{K0(SBs^y>{MltyiC2V$++S zGLPo-#L_xeUA87``NEh@J}08Cx>nQvSzOWfcd~)>FEf(gUfNLFX-Vb6l1pp&-pA_7 zl+xxq0}s?5Em}0f2r7>*%)S;|@IEFjkBW&DefG*HZk-=;HUE6TqQ?iXo(@Q}qij7iIy-nmR?GZ3E5?rN(+c%8+^j=XRzqw~{ zr=7L+*nfx0hc6NSN8>&mGVbH+;{$OYj*$B~?(>7$CS^r#;+m{}vL&ngjlN_VaAED# z-ZCH8%vYTV?09Ex&aygfFArs0>}k}j(|pr{hkMV?nE%-K%=mF9D1ml9H#8^XG@ZCt zksotYkMP5hgAZDpoQk!#i#<|$(6mVpkBKI)qkc1zGS2nk{FsZCf_{~8&Z49_3!};` z^S_9sd{37C_eWCT`&9qcNQ&+oSO3LGN-gV3H(z57T`GFDA9Z-un30EzLeUr}h_tduDxn{F@TwI9D`ErF^A>s20HlIsyWVk@W6-vo>k-v4We>lDU z$hofk!?w?FEPH+BT-SW*{moDO>mPjSy~h0e(z#~WypJ;#44g?=1~o}<;Lya+?<}vo zB5y}Cd0|85``cfI(Esx`4!O4VKkHeuf4RoBLvWmXbx6$N_0f}8cTTMK+wRO_OnhBG z{P2gY(wA#qh{sOx8hod~*dgZRD))Q+nQk4oOXm!~usDDC_3%U|qg5eWa%B#&*wrhI z>K9&gEcS9!ouMt=PI+d~WuV&5iHRjX?vZ4yf+x9AN)8 zYI1?ZI5+#n_WK*}Pi4n!dfD?{zXr!AG%U!W=LEduxzD&65O*#4=7)g5jjOtwtjNyU zu+eo#mpI>NZ&s|&!8U&C(tSeH&OL30X3RUTnR?c?v$5HPkki?Y%p$vmcbt!W8hP7t z=g6h3{ZY-{Xl!iS_$BQdV>8y78?@HK*KAq9!tFb9OA0w7n`i#^TS2ws0N;y~eZ^kn z3eAA1X46%5I>{d5*B(UKpC3ESt7LrVwEIP+E$zzJMQV~;u&qVuQ5{CPzVMCWJ<8hs zE__Hbn1TbrH$|H>m6S`7?Z=ER;Mb=?|rLz z)#F{Z1zu+QE-72GbxyBq4Tgm-nAF=RD}BlQCg)YFubCeZ40}wQ+TeC_WYQC_iTnHY z=(FguB7Or;aGSmPXHkm3^7`$|$baSaue|NO(DxBZ8xh0x>x7ek}q?(0-w_wO*{i9nb81UtrO+OCen2-wty?twJmunO(gK`j9v$81{R+`B%f%t zDQHVOk5194<9R!uwEa+@jMjhos;=?3@A8sm7077);zLa$CN1o8iYNOx*Y%KiO^=sd zd(@^QEec_BDwfh^?Y?2|XI^)wu6kwH{bj_5`?pV}CBd z_x6i7P3pg8D;2BX|IVVJndL=S-|gcqS{k&W|D%j2C9gAP@1@@9zGV`|KSCMwxLNVh zc;}_lo3?shMSc|y*v1g72Uao!>;De@|J6hPS)&p-SD}zecv3UXxj$wS6M8f4r za5gSsv*kiUB)~8QS0NS26ha#Ce5r&@DEKmg zjE%{;7*{~>2tH537jc9bXjFqz056f$7y6GcFi{X2A;dI+T7w!*w7Wv3PL` zluw|<8A9ao2|b8yicpsBJ#Rw|L%P127ZlK>F<~_o$|h5xG9ML6dC^!1VTEuT6L^GL zBZ12o~4->5NHE|!mW8`k|m_@aw#P?hT89kXrkBAWUx;_dEo!?9Ox`#GUm8%v}!wijOM z<8$(5{}Y^Mn+rzV=s)rB{1x%@v`;^@iWz($dROApnJK=Lu~fuw)^$j$u#H1kRG6G+ zy7SV;92LfST`2S2G(c4r(SG>Nxljd7aA0su(&82s&m^nE3U`c7n>5R~*~Uc{yLSgJ ze5tit*mlwO$C=qPDU_M^-8;K2d(n$%|9h{w}sjo+Bm zQDbM%GL5Tn(zIx|Bxz)@$BzET#!hy3J8|pzsICp=?~h3=85;b-ijd_a`aSPj-EPsK zu|Wq)i|cNPm|z!letE07^MMqb`k7L1-lsY{k6vrH?s>>K`_Z#j*6S85-^BhjDeGhT z3%{59&i6l1sop`EZdtrL_D0xkW!yBI2QN3>-1h#%hvsBCkN4D@arKHqGGf$kdYE2qj0mpiY^Ga1mh{)*<#^ys6sbw$TlO9o#1G^%u;Nr2g{lC2_i z^G3#jbmzBiH{Y0HHqes<;(T-InEhL;_T8N@$=SSYDl@ch|05;ahm(5BhNj~=_- zsyFoT?L#9Du5dhXa(CSuFW!E#?zFE=F8aXh*r(|5TEBbTm1x*AH*Ul$nrRi3>l_ik zVe@AH7244|e0afpab-gX+YYa$nwPk#KPCJ47WkmnEmqmBt@qsb@@U`FvgXvq{m(f3 z!(t!lKh$x;r&Z%NRNcEP={ILik=U^ZGoj@Ot3lRLF8_2kDakDAIPS6Q?X9=xHl+;9 z>)JbAx$Vel*2T;{*0-ip-(GiJyC?J1@coa?`Tz_q*vDI~9njfao3X4*ldSB!%;8xFjV>SVE@HXluIkg6XxHEL{kN&UOP?LR^x~dJVOFzNoA;eO+?5UUtsm$;?BuY*xSR zzIr%)JIB3wnCix=^TX_0J={G!E!EP?=fqXx3&)QI9A11kH+u7%&Ti~(P^(lECpDB( z?Wxm)x#odfmPl6{0u0F zOzLyMi3!zMnTRZ|3T5xfg2+&Q80u-#poSw^QkH73|7u|axW-TzxmLAbsvGU1M*qOr)hzB1gbVg7~nI*!wJe*uCrhoYpC}|=m6q3YP zEm_kQDq?El;}U8L0I$~*1di)b5ZfN1d@5N3nXKmw#gL(qYE2S~igvOb$Qqa|6vVcK za>tI2EFfJ2UAr4u%NS-kUHRhA1*2JC)y)O;oP-#LaU?<+#)Yrc^Q8hdU%{30aREob z6;M4O|B7%0g8z#$WuOtnpk^ClyFe&gS|NF!~G*Nn&7p zD0K{#hruQ=R3!$>z|ihQwsi%pO;8p2R65+2ET;`+jTumgmFo7RYp8GySvZ!2JXxC{ zQ`A@|DSFJ|n4-fskAiHF;cFMQzaeEpmK!!kXcj55Srk%uDP&#jp}Hc_z-?q*W~e_* ziUaWf0|4*=@Sx52?hB<_rD~--ibznYwKb)Xm+C?9?Wb@WlW+!i_xYcMlV+GuehR7yIqu*z09vH@3`$hWVl;#n#2h$% zlg>9Fi+IBv0UHR_J-q}#b$Nr(g45xxzoxbXj5mV&K;h!*EGTkcokb@l$5>xbc{Bwf zWsPd4AjE*p`kOO0s5*;+`ca{@a5W`{N|gqk6Q z6jUfRUCpSfHbIuCnn~$RMNCEn6){nNDq?CQsfaO>ijahgm^3N;kDwwZH3}|>rXt1& zsDca<1R_J${qA!yikywede|&ft#4VQYD2+!giv)g%h55U6(xubM5mHO&!i%9 zP!NizlC_{o(kD?7N}=jhmZPp#G^N%MkZQ~@4B%N#O=*AHKr=n1-We$MH7Q6U4S_*O zhcU^37L1%p&B$pYsfd|CQj4V9BpA&JK*2AEYidgSvx5QkWGZsDBvI!@HPtxzgFUDD zibk1K+X5;5c>>5=nz8aIYN{p2r;f2A#@B>*KydL&?~c32r<1* z!cQbgByY5N&NzhVN8B0?pje>bYo+u|gHG~$*&ezz!5Ilel zj?Hx-BU4mGO2jSYhm&Aeo2V1xU<`ch+sZ|4UUaa z5SvQ60x<0WbCMP-07+A56F%QU7ON!U!O8nAj}0b0cni@}CW%yPG>Jrwe_}8I;RwWs z*ck=zCNI|#aS5>!ZH;^P-K)V?B(K)Uh=j<`fWh|N4&Vpqp)ri>cdr8;h-GUNzT$x_ z^3LRocqj`6v9IcR;4DJuJVG$qBrmKqLg*-rvW_Q67Z%updII1&i4fBf7=v;KegaRR zORy`2-8CKORF}bza@bvldFnKn&00s^a5iNGYD3T3QT$FaZTOalcB zJ=J=y_?>>WpO_G<)M$U(eFs{{6IxG+T&~s_yeKa{QNcklw83QZLP2a`L(ugsN5^W? zKLMkjVQ{5LHA&U|8@iJ&A8E6F(U*b9zNyeR75c*D$6zrKmF&wPU7*i>S$ZIWG=v8H zI^dcydMF_PVrT<8nfmk7C~!WA?LnGlmMDlFrT3|5;6kt}X$XCwA@q@k&?g!~RWyXE z0cE<*U!l?wqR|ne(-AVF>jdx_?f+x%OW@n6j{j#RA6m!GeFKRc14$ruY{zz-5RTkV zh@FHagrog|EUj%3SrU>QCls1+U!@QVg-}9)Lc@Kww9o^}4gI%3DMv3#FWPd1ltQ5e z?EmNc_U-Du^=h?J>;yveNmk?C)yz9)-prdfZyteTRWEZjV?b0eVVwZ4Le&jUl@Gh`0NM2`dZOI0Gn;W>KVOQEbYiVjO3x9rHiN zap8EXG8#yo!_D@uq2-CS8(qm^d~M?Jmpw!g4xj8H+Q#9ahp3yw7+%lfaM(k1I)`H( zqQx9O)kAbFhegqPZW7Vgyv?;CHkJh0wUu4>r=IJHemIEe!9he14I=u{Afg`+BABa8 z;f&J<8RpJ{y@W~dFZm$;95?WxoL(Tp*rL2dq`XX|yh4Ow2Ez&cmI$K_VE}uch+ZSY zSOeRcwkV{$PDFnqf>q5X+=md+Uy0~yg=ninbd5svErsY>g$;C2eDrOF;EbT>i-~Sj zh+Zrv`i??$lR|W}0x5$3rH8(&5N%hOn9!|?&gr))M0Y4ecPd18DMWWGME58}_bNp9 zDWu%55PeS}x?Lf9Kq2~}LiC_Q^pHaIBZcV43egV~qF)sgJ**Htq7eN|A$n9HdO{)P zF@@-bVxnIc6ZA7-N#-eq=xK%M9WT)iFVVYRqRm9~o|kBO0r`d!d1}E(GjOTHr5=|C z$l**PwXhM;EL;vF@(rC#bU2Z^=?J`aB+f8dsnAhGYAqYE<`Su+<`FSp;(UlTCZXW8 z1wgS7`e8AC+JwszT$bW;G?DLng_u_MsKv{epcA#=$#Ps);Ifk6UX4H2;Bp*RsS1d` zj6Y5$QhURIo>54pXBAR=PsN`JT)J`DfHG_ZbQ&&S!R2&Z&d`UJ-hX&WrA@f=Pe5T?Bqr)=E<7g(2R#8+jEUK7!xDdwUG50un$%0iGr4okPu;T;KkhY;}LCY%t zqCjUjvXRMZD4B`|Qk%S((n1}k)udG zmq$rIwm=k_lI%};)K#S}evusPQ^7W6b}4kAOZ}INZ3_LTz%GT}gKheAuK!?v+S#VC z^CHJCTDO3jGHg6#CE5c~17IF%)x&gGtKf#JQ=zzE&wS zKkX$B)0hF0IA)j*luas{qZ!rTMz`juWQMXq?*uH~x5SPOCBxBxXp`ESqp~Ghw01FO zq0oGuwTlI_bepN_WV6}bCW$`y8tlap zo`(Sv#~kN}ur%x6!o}T85%a=~g2?R9jCyZOdS1u`(HI7ed7)q|LZ%L0wEUR)3;i%A zS1ddbo3?y7~y9J}xsHYY@oiY}eZKxM%>f&`0#-R*6z4H85x z$U+!`ETkgHyalFc>S8L`r@H03PdNKHa|T*CMJG?@ zNunT}R=H%tY7tJ|6_bP5on`7oU5Iqe2yY+$_tAIEPr94*9rMEoc4)upJByxka?73fs$fW&*l?PMnF<)Ch z&hp?|v6nVz!rdTk`K&nDX*qQzWNc;s$e3Y7GCjv!ErK{;dgqPCJ2R;>Q3gfPJk~TK zb@NeHVV{2^5)MWzw(p`tvyU3HTg-!TX{E@W!;(ux0M)alL&NoVCxVO zJ%l|VeACz+9L83q+c}H{{JS`eIIDX(j5sT74Z#O-R>p4;opnFI50ZCt7{P3}aTq~_ zw{jT4YQ}x+9=nI%N9dq|6WdK5;P;0M_(vc#UM~XMk!F+=0g}f1h+?~s{}!9fjCZhI z<;VO!Rze=-@C4x<#DN>XokT>B@OLVR=ot=Uv)ZpYe6WBA(L^XWJ`#z~p-MS(hIxwD$T9Amv{Y|l`wlNNK zHV|B=C6WjO7-G2zwO$fWXgv1x4v(?SpSE`mJ9js6uDO1Zfpe8ioa>fj!L2^(G2_^< zZOD#uAql&QdkgGUW??^b@Be|1Pr@a=;OBymGqJE4)tPzGpeW74n2i<2)>S3Cz@a*1 z;l2~aJOw&zyg-o&lY@WrdU!>N>JH9aw$ z8jmp8s;Ta9XFK>hE5m+wAHzz!Fm@Be`s^82{Q@zpZq;sZ#igI;xz*=*SXJ%0wB(D% zrGrxXuT1>zuVE&T$qEHeTIx5r}b5iJl8Ctb1YZTr}DPq1sLJ-e2D(b!dOZ;yARTyg5H z`#5z^aB7)7rw;z2ajK6Q0adM9RyV-DA$5;1>R@|D9r8tERCQy@t;6b`eM9P=7*dDW zbL!A98mA7?ZPoSRkQQ@g0_<~L?Gb(*YR|93zG(b9s6Ckqq{2a0y!ybtv2{<3t;6hj zb@&&JS4Zh%YgbZB1Y^;Z7Iint+UIcHBV0S&o@+;Z(YSVav?CDgjL*o$;o3$F}u)tl&Ii@)YyU!c$#Gr}uVAi{2pNE~S| z7^C(k!LZ@NqR#YU1Ne~t?G%P6F*b~kzLB$gWuVt*iCah6bL-f>oLfu6!APttWSYg` zSmB;)uD#DRne|Or*q&wNvf0bR6F*B_JJz0S$L&pA%SOkxKu~Lq#nw3m*@Aa{ZLPsj zRaDdWKw&l5{HbNEhE*UYbh4OYgOn{|9O zUjFeutH9h3wi|8O@%G%h|6b0mWx-fyyfUIiQ-P{PS9!o{T%PI$#F;6 zuG$7lKkjGT-=23T>`lBY&788?21Apbsd!aqARMU@=4cq5`#iCX;QKrXdt~&TV9&w+ zy@`V@oCa+u$IvA(mgz1xETn_v&_YV_N4>ZE?=)IG4PF{crBNMdGV zRa-I{uM$`oENy*Y;rd6ufOD~2Io3$S($85BCfRdt#ei{cI>E|r+c$3EHZWvaARev? zwN{4XlIu&p?Rvz0X5WZw&dxIJ92+41t+3_ad=D6Km$+jOuy9Vp@K7*!N{eW0pLs0N z&Sr4T(6v6Xh{mtYfw->$@i}vfnaNhI>1KHH4s)vZ85xKVvSnoT;Js-e&WVf1Xd62(S)bEX$8JPr4QZv5`!>D@dyA8gOlMPFE+9vlfryEasXy4Gn` zT1fY-ft4-yEgU?I9SqyU&K*T0gn}$+ICxWQO;zT0NGNiO;+M(pa4OhQ83;xywP-34 z)?6R@iA-w@L%1^@(N68sy4?TPNGcc7*5ja2BwIuNx;mct3}?d`a0e09@iS~$>bVPu z%J^|&3iYtOckD3RwR2n0g2f@NEf|ZoIsFFs*>9G~zd@opc8+O0ioA2kb9VwS624EM z=Grpq!6~w=<#Bp7PA^4LI~5u1aGGnq18l;ucfSMCc(Q(7Xb zrBDDAHqaGGA%h(VhvTUR-jO4DqP>-{Txc0zMoif)Ba}XCUK)hPac%NWk|LhrxOVjN%(G*utQNM0Q4* zk$~?V{#zvAyNAOgksOf2NWk|bhrysY_7Wd4Dc+w)5M3%I(Uo)HSdU7v9I+`S$IEiW zX2#@rNTP=Xc}Sus9I?sL$N!m#{=$zjGE&Kl3G=K+Y~lz`;~1kG6jGcL=^wnJgLKnMA%Kh3G82 zeKwJLRHn3M?2Jt3Oz?%4vrvp&o-9`%v)5~hWuufnbvF01oWam1=@~}LN9q#p=k*XCv}IWbwyJNr2Pv)9TkS7@vamz;93Krlfv=!4Y!-odpN1y zoAXKaK1ykc&Tupkfe8))LQXvh0|Ng_&cvCb7+5{*AbGHh*Y2eEbm>sDQD)6TNMIO_ zt`9`Qp*#Ams2HD6Tom;RUQ~9pIy(||wprAI>_r`I7L|9xlKIUm);H|vx3cOvlCL?7 zsOKzp+D+EOr;sPuT0CbX zgw__`;16M<9!P~_(JF|14;*~L=dFHahXQ(EA@=`@VZ{FD(ooh0GMlAHW{cwNZ8O5! zHcO6Pcvrtw)yl(WL5oq)8D=N?vKMr$wV>g6QVaU$Hr+k&rS+k-wPtD6?4=!NU)qJM zRy^Ks#l;ES1}B&etD3q{G0R($y}W%CQ6LiWr#b>De`g>S?9h_Dx#O`&IJoiIeyhW; ziqmy?Xb{&pP&Os3^u~!~P&$LM*P_O3b*6N*^;%+Msv{h2_iK@)=8wiw{$Q*Vf43!K zo&IHWTb}N>nxH4Fy3;gOP@_R+f0SmbNpV{&(H%&HayJd`9MF2CZGcj<5@l{GVQ&RI z)o+DG`fM~jQdh$gfEY0LDKpDC*iAVn%Zw9;xs^)#yThpte`_G*PbPwXm|DoYY}#G@ zR}EwUNAbVMCEBdUV6z%S`lA}5WQtXT9kywhkNsB-jP^g_J%L_ZWGpW(OtOf_06vs&xtPh{Y=-;m&aC@S5GAw1%=Om<1o^rr;Tj%l@<3Gpg8O zDDA~&X@|QhZ69l(X~~Lr`b}D484i%)GaQvo+ruOBs_c@Z7v9rvmCe{MBT&?|=`+$z zQ8OAp_YQn{N20uG<7bqc@@6)Fp6s^*3+7MS03Kyy{)~20;@k|N=lZP{84aM(OmYPS zh^?i%sY>ovP)5f#b1SDd#57Qb*P(RC zXb~-$G)j1Lo^4ow5_$)qgd>t0qrr|uEE?-F3wcAHg)AJXW*pKHOC{qmv!A!SFQ6ib zh!3KPG8PU%Lk^DzPp#~VM`D4H(b>1UFQ!Kwh7RoNMcwnsFmTd2~r`0^uE=~W!Y(&EJ&#?s<9IEPWcTH{g!A?NurWz$5$3fRCc2zD#qEW z10;zV&S=UfY-?|qM2ql1sM2RP!JVG|i!JKsx>yg#Z$V3J?c$4fpJEink@ksWR>i0o zC*VT+^|w~cZ~#?4=cVnPvS^Hj?3lp36{B%%5CqtOEwXKj;x{BwOzTEnU+SU8d$ESJ z+NzG>Xo9V}TQ%fBie!dUw(`mNws(po6GcNV^A|~ej0Y1*`_n#5k^G({l1Ad8T@pnF zQK(2o_bVcL0mnA$$0kENDz6X`B82vocFe^{)`(DJx`?Tw^-Oq755?)C z(^L_Q$yk9kB1ZYtQE4t96#JzA(qeSOu33yjJ?yM?76hJ_PiLuo%S*mcA;~e{ zUxAm#2>f>A&Dn?r>!MQptPGc72tgT+1r9`?_?b7y5J)y4F2ktEEEV^HsLvqH4V`N9 zs#X42)W3Ey#LS4}y3WRjlY{Rj7tz|M4jm?lMn+pf9V-9wk||<+)uE4cH>!{Fb)(v! zrj_r8=)FlJW{^EeBU+Rdl-i(USG4$Bv{ZL2vCdR@Em|sXSI#}VNAW2yQBKlnyNxN2 zH4e9m&(@>5ClsF`oml5ErBl^6In`k--<6$C8O{vJ=M3@O#E~sUq;=pf+NjyrG+bh+!~b#4s2zq6`=D_fJ!Z=1_C(2$sVdHXOn(il7EmTuRt%q_=mtzUjM1 z^|A$BZ0s&rJGZ6gh+KYKVE(p`+Yiwp!S-ExEbvgaI*z)W8MLE

  • K@wKIwY}1^T@L%-ob=M64fR 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 P!jFGEvye=)W2gTHN$mY) literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302174004-Config.rsc b/MikroMaster/20260302/20260302174004-Config.rsc new file mode 100644 index 0000000..7ffff51 --- /dev/null +++ b/MikroMaster/20260302/20260302174004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 17:40:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302180004-Binary.backup b/MikroMaster/20260302/20260302180004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..f82047b71e441f696258d721b54c04d310c84665 GIT binary patch literal 289184 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302180004-Config.rsc b/MikroMaster/20260302/20260302180004-Config.rsc new file mode 100644 index 0000000..2e91c87 --- /dev/null +++ b/MikroMaster/20260302/20260302180004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 18:00:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302182004-Binary.backup b/MikroMaster/20260302/20260302182004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..44af4c391ef477f1446ccfd4e3835d54759b01ef GIT binary patch literal 289184 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 C8nNxSeuEv~3*dd9Tja6;Q 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%0DrsC5W&Re1_bQ{6b5`LP`YBRHAw0RZ` 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 Q(+fZT@ytRp&5oV^8%mG>#sB~S literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302182004-Config.rsc b/MikroMaster/20260302/20260302182004-Config.rsc new file mode 100644 index 0000000..82c4259 --- /dev/null +++ b/MikroMaster/20260302/20260302182004-Config.rsc @@ -0,0 +1,3958 @@ +# 2026-03-02 18:20:04 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302184004-Binary.backup b/MikroMaster/20260302/20260302184004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..363e42b0ccfdef2d1979c7c669c361f14765f3c8 GIT binary patch literal 289184 zcmeFa2Uru`voL;AfFyt*ARxXX%`UK;o`?kz5D`Sch6PhL5GlbVG#i4VSg~P6#g1ab z-o=8wcSS+5V(*Ft{?BX@#P0iDfA`-1_qh+x?#Z%ecV^DaoS8YZJ6Wq17Un7G$QU7{ zOh{0vV$Bdj6ogOmZRegmZRfg3aVmK%n)KCCaQ8qEQFlt@@QEC z4I!jX(0Cz)plPnZ3B6X^s8$;uYq-XwR@<9w2eDbGiUNWQ_7CIQKTH4< zS)3$ZsgTGBnIg)7Sra`_aBPBt*ygB;LPZFfpen>dRfxomf)Jy+y1JS~55P>0l}ThI zb*ieXt8Mi6fTIlxVpC8R1I`BE*QVGJ>9r z$rP$?I4LlkYC(4C|Rx45`Y>Y^~Hl|(5b501RkVk8uBTM#MoHA zt^>&>HINxWhifvDj~FhwwfY!KC9;^r1Q-+zp^l4E571-ju0PghU!YEu{ycD@p$)ww z_2+@}{Pk@HLMTq(W+H@A_3c6`LhdMtZH!Pp0yY8kbTou#FzraZ03~BB5gSivL1w;l zF%XiREh$0 z^nx1zEVSh0WJ^><9)IgGK%<{Nh7NG8VSM!%jV79Wj7Ae3S%bG;o^*sF$JGRY{SgAj zaA(s_@bD`GI< z_A;k0Z*QEejF+lX0BC(P^g*OX$yW9xr~m5C%lSwk#+n+1AHsU~6xjYbv?YUp=# z7l=TtOs-WW>iWRurxyb_`k^3pJVKN~Ab^Mz2Bbs?#emL3h)E$3VlYe)QoxTW*r{Nb z0K0*pT5vXp3&NPFA=CzSHcS5m5ZH8m8`RkpeH*Tys&9Ky5t@a9*p{R){(}$&2A(9G zF|b%8gc#$QlOs*_I>!njCe@(sm^9F*)|ym}mWXqb6ADRUtkwxYaYhJtt}`vV(f)`I zGq%)wo48cgtL-{>MQWp&4W9TV9o&7mO@Rw?LI}6i+Pb;k*>NE+sJf}BpV1wXU5zC2 zIAwf#4O}q4=wZ_hDhZnoCX3H7f#B+3LL>mzuUd+lSi2p{cHcBKg3)Z*Lo3!)pO)J! zw)f|BKFIGQ(E;FGUVLYunK-@8jT19l*I6(Lp^Akj-b%Nq3LP{_ zpAsiKtXdduHzudC*(tRHK*P|fX+k~qdjNe!5m5BxC;>ntx>}I{kyAe?9H!A{fKo@i z-nU|7OV0}f3I;t!&#&2&Zpqb@>J(^@dee&5i5xl66m#Hr*2+!?06T>TT^n2UngMhN8_ zAzKv0HbICqY!E`E>H-7DFy|m-PHM~Q>S~iOuVs^(xw^XA*l;aFf$PpGaAU)@dR++? z3**c?p&Xdqh=Ndads0qGNoYh$D#>YenO=1eLeeOiDqi6kMZ^S=n(9RMeiWNf00`6~)5aWF{kfVy6p2;8Nq-%$eGmL>VB4-u7 z_>=4f^ov$$H3=%MXPiVCZy2esNB9UrOmi4v!^IkPQi58gFkHVv4?P@Lpdj`fgeXY} zp@|5gNeEHK0fgDGn~V_CIvQHjVK-B+H)nwibff5?pAG*}!@s0D z26p2CqtOUCn=4`^nrKfwXw%^IRM<^{-B{RV!7decwJA^=`Q#{N0{s4+$)YwLfC$Q1 zk`G~fpr->IAD|$1ebR$~iJ=!2A$x@KsK_2gYqbetPtWA!WDin4waOR|nJUh+LGAyj zRf$?cEmcX>a`K;!q~)B65a0|HKn--t7F0jXKNJN*lzIqJ91vo9IqAvg45V^_ohvyr zR9DwQh?xQ`L$QXP4P0$t8m5k8tbkN?b@W2cz<u8d zJvHEXMQeK!z`^s+gy*fJJ|z7 zIxZnrk#J$&-qMG&I1@PGN!;X6e}r zfM!t;Vw%C6N(D_#Zx0+%3?c4A<#5VxrH^b(Qn?ylxQHFW`tI9cF+ItjhX&Xy901 zPdXq8wKf4hqoR>0;}t6S4VzD`qt9oCBEhEu_#=SmLI9t%G)eyrbR8+b z&=HYe8wsuTPlID?-2_OY023e(j0w*f!O)K@ID#;mq+jR^^Oasr!OR6w8BcklQf|Nm z1_w4c+UxG^48L&}q9IDB?1%viSpXi{Q5LHt;^Ny{fLRZmYWkdR<*z zE!4N)R99EC_3eCwP}|QGW1M!&7Q{*TqsWyry@Mw-4EwVd%`R)ej&taJ#dqTeD7G!@`5TgM4*8qE#Agyd;hQ zo*_}y5b7jC?WswW#uHi~4)Dw}Jx0L6b@lBn#y;leQtN6A#_iFeHYs2z9BS(%Jk>MX$Za2w_R)jh9Gub z1U6F!X>x$io28Exj@6qUFt3b52o2MZ;c$d>3T*<6Avv9cN6d0`B)}tv5EN;7Tk4Ob z0SM!332rh<)}Ky+C>v#NWGWaYEC12;0ke-X6@q-E#is#3D+t`0ps>J%&vSGv@Io%^ z=E9CtKSQB41R-Z@T+9`Ug$glGA{G*2f)GoDa_HMBJ7Ut4{1<-|<(QwNT>l%C2ccrw zFH!CRjxJAt{VvK@xLARS<%C#)i$%CtF2)HG<7cJMr4JW=86R}G0qor_+kZ5%n^`?(}&vfUkm=MB>R6ovZNBL z8C;kJzQKA)>;1pPnjRDo-s5)>w#LOcCT7dUTwKhSiP@M~#wIbgboXxMwD0X79qKke z#~9|iZ!qp&(LnyIab|^g4eJ!p!Q1Kg@wOuI7K&xKScr>xA~8>)Lz}TTy?5m6KZD9n!)^XCtlu>{!cwjx^XW z-yl6`v6tdkWBu=CTF2s2Tr5|J36WTiiRC;U+J$8mr!O!lf6^jR{TyvD)xJSH{X(x_ zqTRq>5-Ukbb@ygt?g^?`_raO{o9RnIh}mKuTP!8S9EBLyOs@=H;-=;#|37~VC+oyQHu{5$@(!D5Yz7b6I?Ma6!WEGo>0u;iY2;H zzHJ}Vi(6pyM-^P)&rt?{@*9+|KX3C(-nN&-%hf8S++8Rq*ce7ABm`TI6Vl)2bt_zq ziP-`%&I4OUBoIq<0*;#2^PailwqCnY{+MAN^c}mENv$#8z?uGr5KCJyf64AfvB}DW z-_~n7yZk`LOQg%j=dZEfHd}U}Wi#mIUDtl`j4e39*Gm`>heg z7DlXD`kBiYQ4qPL^f|V`2nzEHcj9?q5MyBW@b1_(%ssff4@rfrHP;7-!Xe0Djf;gs zv4jxIM;B_z7XYxt1i1?soV7sHHRD z=W+r;vTx+XqG;R)gdJ&d`2=_do(`~%9wRBrg>esrBjGNYG z*wP^NONRv@x5i4+di#;6>ij&gA0xY&b2)aNYONL_s3S#RPu5A&b*dau& z|2EKNFOdt^PP$wMNFO2B@?f1DR(cq)mZwX%g#~L^A<*aVSnGpP5I&~Z!|D2PJ*;{| z#sw2K)L#Hg-!vC;)myhV#d37)R!LHX* zK_)1OZ3`GU)Jn~TRpL4b!8$#x@-u0`{ZmugpMw=csy-t3P6@M}*eR7vC>n?mqfgN; zYAocXSal@>?Ti@RNm{h7`xzh_kcvzlW5SX-6Bfl7RnJhCpCkuku!CfW`wEip>DOck$Ht71LnM3PcQ=+P#Z@no^8#F{m^zWV>b zu`db&djWWqqSY-cFkwxBNy*ZWN9O16ih>i0wa}}5T%yLKW8z(Iu&eitfN~4gETF~B=d4~ zId!l~2%8}h8RWpQ=m_g*hG%!zr$Ga$tPo;gEf6F$FyUeyAH&!?oBJlJRSAS=kV+#{ zCBup(Z~&z6nCezONY;f^s#XXw!Urr-!UBD)D#~3VBUddU867rA6@d-l8KrLnu7)w)fOxGr{WFZ7O0007+ybZzvEARJdI%x$KXFyh;IdEtl{a}%6+90@8 z$TZRAcEB<`JeKTAF56myv87AliB(0_EE^lg5pgPY>Ztz&6l6v+<#(W<%axj#{|F3Z z4kVe707U#5CFq1KTJ;|p4KnkQ_B(ViRuge5Es^)-Xn?Y#n4>D-Wm0?pD}Ja+_@UPW z0sv>w4X{9t5!IXpWT`{io9)THhdS{G>|#X3NtCg`!!kl0H(AfeAZM_FJjm%3`@W~a~Ns?aNnhX|oL`s<$}ge3Z;pl1l7kDxI0>&2D&Hmn6V z2Cah-`ar%;q1&3p!a6s+H-T`*yycsHIfE`Pme&hnPeLeVHX|DDWQ zI?eJlx6a2nxu02Xb@!qp4WeguUb5B4pRacBapA1Go%@;eITihv*T1yA!iB!%d}sUJ z?WgsLd3inkU4@Thw;lgbZDS*fyRkcZI2?}UD-Pd@x0-iJ{BUuK!`S9A@6Sxstl#@&(P<+ye{+RiAcT;bcK+~VNuM`2dQRl6^HWJWJhw0SuCU`l#Lash8@9itv@8)uE$&Th0& z(?o%C%0_EF-6xqwOq~94Kv#=(_5rSrm2-Mbt=7Cv>yYhu@vQZuU2J>RP7M!2n ztG?u;^>BK(;jY)s>`Wag=WgzFICwq0-_veGFV8$!moiarSkKgqC* zU9tV?^zG|koyv$!X;wrZerZQ%@%7axb#&YYlecNF)7lhWU`G4ct*G;`bI;^bkzoFV zi$j%bS4EAT@j6m4nG{nq;Q_1Ifo-g{HuHN&DEl1GgHXgof=&m>#Z z!;ky<-NX-sjzi5#*w^|DqnSIa8jXt1RwfKdZ2RGMmt~#_@u^er@>4jMgTLD;?w?LR!*h+{LnJOX`KTLiv&@%3hS=On*Q4|vi}lIQzkzkSQm?ZU>m zwj0sRJmISCE6vplQI1!};G>KSLfh1{Aj0M{@od&o>Z$!*-IBB!3x?iX_;PQT!G8aQ zZEJe<@!Gd(8(v&kb9ZU+hRkzI#p^8ECd{%^c-32l~>72piO*b@R z^>MJ567TPxqw>2G^+A1!)$(BvNk)19*9k=YvoRo$35!3tK_ne>7D77$BrW|`J z_C2$F$c=sH+RC~OIdn(raBcG&*Ga9sw(j*QF5vJMzHG6;Of~((xc!1~TEd-vq4grR zO`kKV`N2;0=P!wMZ=cyoVBx&(=~BiezldPpr+M)$x1B9Hy=#rzj@d^{5yD)IunZ$d zEQ4;GN25}xR4b$Fk=Yh%bLY}|ImE@HmENg$F>_;Pi_x7%zcr^&OpOr6!A&uyF|9k@ z*qYis47bH>;0Mdv{0k+Hn_(m(iZj%jTEI&!c=~ zP$#u*+%=XT?P zu_vG0uAh8OtT4W>&Db<>dO!7x%}MzaXVIBUy#@WMnIA>_Hct`NYnv=KvuQSCXz`f0 z!(Z499Xrdryma~A`+0R=HF_T8F=V8vz=Zprf7o}#{LA!X#PVnPakHs33Zg8|pt7+H zss~obnAW|a1%*;gr_-oLd00dE-IxyJ#%O6wF)}itQEFOL%nbf*4VP0fq`SBd-Ii`+ zJ2kU&+}QSEaW-4#KbvH~&-!`DA*>Nx>`J%CY)9CjP0e4pPg3Fc=XP10()Rte3bQk3 zF^=KR6bij5));d&{KlxG?et0EYMkw%^oWJo)I+6?^2A!gUF*`_Fqe#9GlMl;>_j)i zSQx|DI4a$YLZx7yaIz7-8P)`I%X7(d8tqu?S+ZKs!ZD7AOdX45P>hUOEsZI3%EeSF zok~xCLr;H+o}(mGfAsl7%~q9WD@Si`Y5cxL)wrefo=ZYo`fNK*b#gswJdJ*I z=+u$x2VI)&b8eDx_T$$buB<$_ux>m1BV9p8mN)^0}QbKdLj@vuC1b{VNTr=btv;J$gUWq2YXGN7j^w3tHT3 z)t&dz;WcYIJJn=$b?HC;04Ooxi;=Fg|@ znY!BYWy@VgTU2MCkL;aTagt7ZBYm*1h3DLo<8jV{y;0}z*&L@!Y#Z+;lo_#oW^FcZ z)FgXG?2Ej$EfZz$R&HFC-Y}?_aOw5Ek@M`87w%4<-0ow`r<14T%=AC|I_vE09_t3w zi>_$C52c+czSbk&SN3*p-`QThswq$99(^lvJ`Q#{+ka`aebEVN%c~)mY*%&2vZg8G z>(g&7 z7fAU6DOb)HVG6}Kgz)crOyl7n-}97G5OQ|Icyc*UAyi-r0UMLEaXBH9i+FsVoG-&9 z5-u(f5&S{F69&C%`elsO1$Au`0Iz_?6I!P*LYAmjYEzv;2@N4p%c7n9;fpgC5Oxg+ z3-xyjRjIU2y>N)X!uycAx7qa(RahHgjCk~nfQV}K=;<*KQ7t%-w6bbyBMvNUr(clbegqUZ32-|4KBvPIT*P?R6~Gqa5ls= zAgb|y6e{^ubmQu*X4=)er&qPU;aGkrFtMPORodg_H1=@*%t!a}?4{NdO=o*Jo}hGV z)8$UHcxHEeR0Y2`-0kgl~G)`r3hX-5Nz(<(SzpEpN?Ym*+q4j{csrt&CyJb z%U)!XcY5ZztG<$SUK^Xr14WSoubIwpShwI-iwC<}T%2`i?x2F!S_`j|^#gWC1P0qz zl(f+F9V;Q`S3UMxb}U$RdwwPI+fZFUsD*69B*j7d%!ETBgsQdnPN$I;j9&fRUFY>* zTy?($Ej;_`R{fwCPX@nfI{(gzT=zvU(sJ!qKeZN!&TKr~%KPHzqKZe(?|L^#+a?~m zpf6>fl)kUoF4k(Vqn3{v=%O3x@38dOU&b~lqrVs1pc*0$Gzw+~VF5C>!N80ulxixa zc7)@5V);dcBXwi%yF)hLxlPfGU}PP3==G*zZal^|+@C_BH^JO67sGFiI@(qrbx6U# z3~+omW&z=^hK=Y>m?QR2or_rv@f)%{%a^q<86))OgpR zoEKBi&uTuf??dX|4$t1b4wgF&$-jjkD2itKkH5SvCGTi(=iN%T7J-5x-Dol5cA?`p zoIks|SMana$0AkcctEG^2ih&LI^xu(?kJPYjqhFvT~`f4?eC>c^y6j>3_f+Ejx2J! za*jXK(xob})0QcT;m4*q-nM-hc4|l|KWNXJ!iRS|S8%*0Di_V#ou9V2AaZl~{h%2u zR=r#oajd~${xr9_CwqmCSiocTci*F(D{W$zI|XlU`ZDdre(Ct=L&>kwOg|j#{hFo- zToy9-^wXsusT&6b(E=r1i=9lycUp(P-kf{p$m(SKYwHhL?7rd0D7_I_x^3&`L$mzdv@9tiJ1xkd2cc?MoE2O z5Cte>Lx=(tv>`5D0`^4Cf0)A_-4| zVQh>e5fKWR5L4hnLMoLDcswB{zy*X{hVytFo)8mpFd>Ie$VdzSdlmy};eXFk01Mwq z#>UwkHdiXZBqAwSgbQ%FjEgA*1Y5{s^EooG?qR`91u0QqET}=+BDH&17*l82)AiXC zbx_wf9hFf^A408l3W%3kqpscCz-M;k$|$9bP;22!Iu2mk*IeZvtCC7$bymKQ_ZL>a zA#VacvPhp%0cm2e0+> zzXOC{`32>zZ`M_p<}W$7xaZ1{McJmwlaDM~`o!wwj6M{m({akQ<-ypNu(v)3l&I&t z@`*0j#~8Oq>CBTS8;smjcB1tlzw(QULq;2tn%ZU$neUi0?8%l+iy2oht{rS9GA7bG z_iMD%?p?v|C(SNt(*~!^?wuJO-`ABLxF@*ieni}@ggwcYdp=U$WM0YdXxWRsBGLZB znMJ$(%bN~-HHY&qfH7eF`N)mpQF|7y?A&Eo+f!X5W0U&l1q!Cjzvgl`?xc;wq=Cn( zPHeD|+a2oDd_H^6izn~TnRYl|u*I8w)$IJ!cj*^)OzhQeQ-k{f%@!qG#p&1IuD5;B zg%xa)|G0CT{+rSkPu{<_sm?EuVUllVJBu2#-w2~oDAl!AHEE?GydGz|>`**gT;8C; z{+a9Boaz3B&HvpCYORPH=@-e4-RwUGwj5RD zzU{)Hs#kj(^*XjSE_bl@-mK;YbvNBg$Xj@#OV;dZ6Q(4T7g+qWd)kU>*@fFC1I{hp zGp`Tx`GrZh!d^|1y>GX?WTT=?s~mtGs3JqV}$j-J50jwoMJ6 z+GN&^5uNe{PoG^(9bj9!>VBOQ@vA!82|WX@-t=wTVjDl~lsLrrt;hWXJp*DT&h{7R zt5dvMiATgNf4H`uO~vK0d$$Q=%csPStCnv|Zrl?qYT&l`=Cz74|Dl^Ux-pEfNA9~! z_xSD!*|y^4!&wxo)rYeV&f-Q+WO*H|xR8?*R|*y=C2U4P4$IIpf{<~Omrp{1(9}=k9UYB$UE5G$J^bT?Jel&$LYxP_2vK2 zPGU0Pn_v{MkkZyvrPa2OD!@XrmFO&_xNj|_?_`$R{owI6){z-lM+_{3@=RwPF)Ugp zCDvU(bV==53G%dDYRnq5AKetp8Ucpkn9i=j!K@KtI4;CEI2RK{{MJ2wrN-7wII>;R zSv2%*@4c-?bDuZ)#8`8#*OZJWucKY(zq%2!(m%Ra_Pw%opAsG%T6xB5U!`eYbfE|9 zMF*RO?I-pWMO|N+(K0;l6l09%mGba4MpwIMec0bn-u`&#?SAL@nmzGnd$MiiV5ue71r10?I)jh|jJFJhkKmYGX$ zU3qz{@A)&227It|Dk`_Cld~nb-R}37T^q)2tL(X8$qMF>J*O8PGJbuviCf=seI_i4 z+BA1-^UP5P_Vzt}IjCfEsyU}FnyPG`jC~4iux9k4lWUeVJ?{H5#wsFXa&JxRL#ecY zqe~t4PF3mbk`7q=Z|#sT-SW+~?2@fhyW738x_qvGYJ5evz*kQ~M_hdP)d15V)oqnU zSIQltP*@miH@Ot68euo)$ z`SM|jjMbWXg>LUW<5cr4jhYROd)>EXi0DG5=cjj(5k5PqItC5A#3RX5YzK@yfM{f6CX@>f#Gl-0kIa(}$*=lPt?!4yI+mrp2UTmr`=a-l#d zl1uqGpU>sVF`UPh%Y-<=<`Wo?&E|4s5=_eHb0iXiL+}U=M$YHoQ&2FU!%OGRmY9Mq z74QW-9G9{MG6|QQtA8-FRapM(>9=Mv(j8ud{NeQbp!W1@{#(9)H|un6l1p+UeYSrImB%FFLV=wQ7(d@npl-?b`02IpUu>saf_fS8l9RzQ8-6$=r-x>8$fJ^YhnHNWcA^%ZKk<)ArmW z&#rC8o!!YW;UaXAhADjBzR0e#vHRh0$AWIL7wK^`ZjPs}+;Zh;LTKwb4OInun_o80 z+#M~y)rwL!e&4Ev8S>rv9L)IB+Pwn8^b*pUI{q?L%Q<&zNRuL6p zi320LjVxSywT@rvzz1taPFt6MfOXVl;=>hA8BJS{>pSYm6rXGVB)YU6xTUlXA#VD( z&b_(r_2(qB{;6!ddfZuyjZO^|?<&r&N#5_67uZAD&DJeyix-`hBfQZ5;bBYFf;ah2 zo3lE^k9o8;XL|LbZRKO8Z=Tq4zuTZ|1p|hbrl}Yo7uwu6WvLgo-tr)k*eUlj8QyV& z`C;ic{_SC=_AjG{IYcG|PrlbpI5w~3)(oSo6H5dpaaUY=cHhu!7d>J3-|W64J70O%ZL@{TF!3?P ze3Q0V%G$*4>sKhdJ#zIB_VIT4@V4{3DX-LX+Vs9&EN3b2HpxBenY4A>rGrsim*^JL zj?BC*S=9X4((=3ez3%VP6fAkx^7e4;hvMPrx~sf$PP&_M=fTe#H+?;)aFup&NqAxW z%;V4GyNt8@HYxI0{)9V>-I94r%am$0mAjsflzrHBwCF>lpzNmM<7^8)4Eqoi#)XP6(U8zS()hNkGlM!` z4*wLFAvw|TWs|(%w2px}8@zD0t>xU?o1TWPsnd4l(;>T)y3IvH=bUcP<7`A9J7v2` zOI}Y5-@bKs=9<~hMH#ElZx7sO_7A6gVCcQIty9)tXmMaw$peYq_U3(htkpbdW8(9| z#!8aOKWMTMb?Ab$(~5_0TvjmLp+&$;m%X{AOU9f}PV2V5t;gvBMzhX``3=6+?+q(+ z!UG6JE`G-1vyI+|QxVv|UWk$#4kQ^ z$JE>B;&X0)oH%gvMhKtQ0|%ilmO-i1I|#!gPx&3|EeZX~e*7)t{#On{14CGqX7-Kh z{H15`!r5qL8mrh}Gfr{eIbrI7dF!4SzcU`5Fz&%@+1-8K_L27rr=Pz)&b|dL@e-wx z@dw_yHO;m1^TwXS(&L*}6wdl+Lp15u{6?QU-2O#@Y3z}NX}2!z>OR_%c9@>kqGv)1 z_kQ+`elMg}rPAGVi$3+L+ShF+?f%j6Mc1NQ4;_dmmt7C{=Rfg0Y`Vt#u=TR_g84ao z_lof^?=7VSX3M88J-yiVtWoRhg|m+AY&o53OnsDi?|Ivi(lgK3>_0Yn)ZTZ#W4wbe z$CT&Q-Ix%zaoCYF+YFo}_llb@aTv zsl#($ugJlyrV{_BLv)@&C>HXiBS2qQ%MmEvo4Tai)q(Ew59eH*)9ccp23Z3{Uj!(> zHxYj|(xm+pGTdYbwtlo-|Hc!YHR3A{xk=l-nhD)H#_ij_>Oh>HQqa> z-B8p1j}DGHu{)`pxK;eQZ>qZP~I5^kU1-CUcsN zOrF+v@?e|kMqSSpzV}(zY*PoHa5Ja*eG2&t83$&Ky3~rtT(G!uvSxIT^@SJavx2V8 zc%0*WKz_2<&6#bz{*kv~Yi_riR5)6C^ttrrC~e8uXEBAtZ8JB1OkL-cmv*2}gFV|t zNk(P;*@A|4CJC%r?beDqZ~K|2@K?Hf>N& zoq^ud`|ujPAM$=j@oqP)s>jm)vQFV)iqigj4O3V$O64C~)h)&phLkUw%RCwBypy4vACW&3WIy|N3>3JB=D`OJmNu z-{$?uG=JqnonMqe$-puw!+(*qt<4-!q&QS2C_S~SxnL!&;qJ#L?7r}if?dL$>~rqk zioa{|{{1$q$HsQqqA&fe@8?6-ekVT3kkd_}&aUVXASX-n#f4vq734+vvq6fm4!V@^)|dzre3@}_1@x5Mou2R&s2AQo!8>>x}4QVJUX|&wET@K ztNBN)o!h7#`?n04X3}cyn3yEaW7Iu#eee0Vx1D}jcF&^f`nv<$EY;~udgQ5@^F7#! zlTOX)b+#uyTtG=*uZU~zP^e(Wor$0PYTJ8HicN9f9&*Z+VPo=zVGG9h^NZ_yu<5Au z^TQ`hSUflM-odO#f}t%wJnJ4IR9jv~)~C8?N>&PZ`OVXnxk)=q?T1W0fArMTDB34_ zgtKj7^@Db0*D_u|eARoZtGQc?oW@;_E}U}r{FYT?v>TqsEuLLcd12S6_6tmAk;&E; zIFuwL-vHaU!bf4D@WkQV2Q-~BYK2IT6$V5CTMFO1;!^|hWr=vJIU^`_Eh899UbxIT+*{ zu_3M6kbK0`|NQR&AqlfIHX(7QQjCpSrqhuNO^WE(mtWa2Zma1B(=_L^&vx(DyyWzA z*vWlRdT{Q}(>ZUR9Y1ZlUDBtU-|+eF3!Y4pnb|!uNqBu~lt=rKx%b<7$F*L4Zi!8A ze#$(W&l5}QSas=|tmO-1Hu;>4y5?F<`)6@^+uz9s(!b0|etT&{Nv9>13yUwW;d>vi zD^p6F?+iRxd$efL2qUOCTD|i{Y&)yYXWT{mSeSnP(w$EP%Q`dNZz`^CZG?nj3 zPEDGM6UO85czmf$!REnjc^saMBjI8SIZq775dRl zFwcG-_xbT0^OcY4&k64m=Ii4V*2$YA6X75a>S3A6;pDb0bjA47k z+xRrdGBKHRU~gmhrzbxSNm&pu{V=ggzUDFOZc5hAVikWy^RH+cLX|3HxQ|83Fy zZ0YbtB0|pRN#$~moJR;mm_Wdn<9r?=5lA>}o>U+qBnmDr;&TNeHZBpd6$-XcD#iFh zOfFzcC8TrxJ@rjG*WXjydgq$W=5cW$F6YY?a)pG?C)j*0!I9wt30Ej3-$nk`x&Gnw z_9N%I@(6+-{d+c@Of*8i+$&Hm*Y*ABr6?zJH?N7hGAUfnsd+Hbovi!t$a z{qQ3nvPxdAc_AJ<#cS~00%M1mQ>)zX_h-6w+%BCn{Nm#L;Wxq)os3q6Y{`{5#A4U3 zHmYBE$+7g)r5nelj})wV)W|3J`jA#YuzOdU|&)j7ca zZPerfiE(cBi|rK~E2gqzHofe5zh8qB6B-ue&~pM_^4w?K3W&R&eCtC%;Ko(mO;%** zY}n|!qf4Ccvo|Z&=U^K@b?H8#Y3H6cLo?=`&`dpN+u7J`LdcnHN9Jz3g?F8gej0hl za_7jUtOHTa-e_!W+V~~yA7eAtnH#j$!q;qBz{2f2a*GQ&Bb#Ub_FF-<;{e}_lYPZr zFV2TR`ZZYEtRTh?L6p^l8vX?(3)#MM}Ho8G)#F9NP_ZggaWxqpi` zvpsk8-LdJs)6LnDVSe>WqUSz)iCt)mmroou|JJyxS7)^4Suc%zR+$iz;O||xXZ_%! z>@~&*a;)t<8#G>!_@Z#q?1d`pLhnIUSuGBCwRGx!>7|YDof{orJs6Y2o>r$S%kWp5E|}EYCo6r){3aJvtFN0M6bySzo7&(`a%9pIuZaix z_2{$ciXwgkPjH95`Damzzw-L+%gBG_^{>4CPs;0OQ%EM|$YfHffRAx-f=6IDN2n0W zz-0-&pMJ z`|E`Ql({9Ee7D%8$E2Etg12DEWc{OCC>ZeNn@v9s;+T*N1HFA~Y?td4EQ4|d%b*O< z*)Da_5^Bt%r?Eqw&eMnYCzeecQQK?9JibhcF~>|H_l0Fm2dr>QG8RCmS(A@(>g`L0 zT6mZU`}}!CF8r+dJmSB--w)y^URKowH&+)A9JDU_1EZm9^0NikhM1iV5M|%#@=$uV z65D1y^s#-%O#Jnu;7f;lU0nCZ+37>te$L8bL6Yi8eYb17oZ1Lwt&Cm=YX%lwI4qxN zwJB&zJC9D$spEM&pS1l@pN!Uj`Kqq*x9{?jWfjP1{o=z-A|@^Da+)XmIM?;CcukL& zU3=7~BP|MHaw?Y6W$pf9?q^?jr>=Ts*ZpP0hl)FAOjfL(bW3(Jc+d0(7Cf=7JNB}E zmV5ifnUPXQt4%o&JtOr&y1nd6}{r}ZN|5>9FI9H*NN#r~!hOv194vt}bnMA_n zNN_eTVYB5zLL|U21y>;z$rM5!TY<490!%28@Z>x`pHDiM-(%^|8dbu@*nFvkO(^&> zfsBpGxfoYK@CZIn!WVIb7-&?3QUEWJ)ED}XFECLM8zICrfm(waO|-j0rB0Tp<;wV) zLX=OS#2G^5@d-VMZHiEq?mcfq4MV!Vnimw%q%mPN70M=4p)wy8N_o*(2w{bA8xweh zS|fqthZLw0NTHz9toNj_NhkAyb>E^;5WCH`undY=4AG|_+V43 zmg;SB!bRz^Th}~!zTjEWy(I&pyKWmfM#C6mdCdGqVe5e{`tdz(4X#UDbiY|0qxjR_ zm+D1dbV$v1oS9S7^ianhvA569JQugK#kg#K!@=790gYoC-gn_Vf7?LXqRHWF{r1j? zs`NRL-*42ItCz|~yAA7pFnrOaHmFMV@UGdmcM(l}7xDIVx#`#|xBZ;Ztc}Ie8QTl5 z_VGFOvj0g=v&{t~ZuXyeWd4fydD^ERTEz@L7`-d;>C6=0$yh4lH|sj2RoKR%E6PnS zFx`1+V~z>qye^jdZW^E}jc7mo)?BE9CO9}aCTVet@@JCOVTC(Jr%jq=+-&0_i#>Y+ z7rxZmEo{4J`{T^)nH0)Q`|h1xI@v$7O`4pau<+!Xq2=|?3dZ%kUtAq=*}*s?aOZUD zv8Vuc>ysWY<%-ZYeQoC^mA2Ka@F_R#o}G39i{CtbhueqE+orX`S50cOZp7p1v&L^s z>Zq}^XPL&8J84?9Taq*~*keck<6|egyPdrKd{ozl^7qFjmJAL4U`5FC5&fQbt!}qy z(Ac1ZB}H{NL`<*?y0E-e+=W1jP5n%%H}6xOoyV@XTlYLoX30Wt+;x-Lo#C2Z+r?5 z_4M4|{n4(eiahRC`KalO!|y!qzNFdY%ZHaH7R5&rl1?^9=3ZI0Jk}rW4pTd>Z7zMJ zJw+?YoR~A&t4;bbt5!~x8?JO-muE7das3s|o$1lXXzO;LSS=ZN{nMzD{U!lsw~M!m z(5;&p2h*M3w%vSlhS@+*5{L`UrDG0kt=fNY!X#(&(y7eQy8Vw9Zy!?JFfXcUL4M0s z(`MVh^$xfipz*mrj$4tSp5eM>oSXa7n07rL>=#fw_i=a)jiyl38 zyIpVSkvoS+99rRc@YJ5VH($K{WZh|hsa*7d*Rjv;BWwNcb628a&)m2XuV|)KP_A=C z{D#e&{a0v5@9^OT^Tm}79c(+inrdF`rv8-d<6Gc^TDMqbx3=DM-z%ei&&Zln7xzEw z@DGc9wEs}Y37=Mt+fa4?o}}NLIlIMA5$XRu8i5;rck^!@&m$P5Lc)bbQr@Rn-=_IAgZ!LjU1w z^Rr$^>Q}r?^DxK(&BIhTS6vup-|FF>;c2OsUOp$U8DBhcJmARUd%4k@-*k3kcY|7`nmDPU zlxk0%9wd)FQ4rgRRD@82kyLGZx@*U&)!(5~G>pwOdQB3CAA;Gs~*)kgnNINFf49IF^`-UwBZ$t)HK zp=70+h$S?d1hq<`j3o^4zS4JvBNUCcCE=~EuC4~f3lxT`zvifl(pXm<77DED-sfjP zL1a>&15Qk+#>zxwaaAaLPZmUm^21P1lLj>$$&#{Ed;M1n8^AS&!pOC%{ZifFA5eRg z<_d*!U0~-7J1FtXAc+#LjHwG}>cGw%c0fG%FrhPoO3Ew|#^vGUVln;8pFl|yIiZjw z#%jr$u22zE6CamQQvi6qo*-~skAm3t2<21B8pvclXDEgYjZ|xrP*k*&wYpghXkqQU=9A0UdXlDlRTDUa3_QB$vPztH%tE zu_%b$fP~u$1+k$_F3Zsoh7tIM9B$w;U{@BZf-(N$|74BlnmVaKa&k7;kATr6RVh`07fd+0P>oP@id z>6>)E0a?Tw<_Oq8sP5|}0IJIygch6*Z~Zm3C1AV}+y@F5S7$+y`|2z@DLKaag36;Q z2q|k+GX)_AY}VhLu|d^Y6x5FjrG=|0F;o&N3KJp9KL}Ak{Xtm`Cj^rVg6W7Nry|r0 zA*7%}sp)D)RkaDSMAb}6Zz^IkBB+Ro`cn~88%afskyL~vRK%o7;eP}bF{x2-K{ORH zMnDy0kRT8lvhH`EODQKwwFgzqS&oj~20{lV6)_!II^A4ks@KtS{S}1%w*mx^3_eA} z-OP0Vo?) v%lUkV0yVs+lwsRL!V^s?c-_az@i&H<|K<$TWPGvdjYDH6O4FRdf48s7P<KAmrkAm31vQ*N(FfcLL8qm&3NJs#xfnqoQ4wZn3fqKBiz_9;E zlp={l(&sZ(Y8VzM@F(zuSs8@&`*<=KbUFwl*d%}pOoHFxe^O#TivWluX%M`h=nt7N~!CB%Db2z3&nHux7(y+((l6a}%*B7_bjgq|ZrIf@YDnh`?BL3N#g-ATPNJB<+2 z>kOPZ2WH)Q*d0NLv67Au)OI(6C%NmMgr5Q}Rh6+cWzr~^H{^+O!c#+Nq3nE(?F+#J z*x=Y)2Qo56Ris4RR(?1IcD0E*F+N@y9|guW9qs}+B*rUcv7T`%d7{o|f{6&`1K8l$ z2nDgJq$>c^4lpNau>z1Zg*M^yEo8AuA|9N)-}2aC(u21UJ!O(erACuT)c7X`0}zft ze2AS<0B`bgEfJRxE78`tci+7lY(?^Fjf_Z${0tau-|YZ?fF2sdxPJFK;DK1SHsLEC z$Rh7dzKDmiP!Ri?o(Ik$gf1WiqfPR{N+X1h!6@r^f^=blEvP2}u2Tpx9f2_@XW=LC z1iB2n64+hWaZYt9{3wIn6_}^afI0rz8x&z&K8J^K*&-mYT9pV);;B%^YIPj@JI*vv zz|d2z=ZfFySNn+xu}Y2hx7~N3bv&WKO)Cid2(S-M^tb>GF{_+ZTNqi0qpReN&+?OnwX&15wGo4AKSq+?S;X5=cX6 zz^?} zs2WhF>--fe9U&SWAvzr)Bf3ripZ$OAeF=OU)$#wVpfQ>VN@@N)CY8J(&JSxU-2Yea+ik8)9QgkX>8Zb${x)p6G{zh#nk7^w1!p9}Ob<@gRb^ z$`sBxeUM@9EZ9q!1pkr`;?HpdAIj+kB8)A{OGL`cM9M2f7-le>&~J$_+7Je?=ZWYw zB8)Y#ooS0g%Iie*Cn8wYY{GpA5&e~ju2zV)Dn!>PMBh?~u2tAT2gOIs_2}4n?iJlLUgA>beBSOw?cG}LUgY} zbe}@X{R+|d6r$S|q6ZYBA1Xu-Dnt({L_bo9eykAvKq2~7G10>c(IX1c&lI9Z6{05; zQXW%?UMME|bumFd6P9G2Qiz^bh~DuM?eG%4>m}MuMDKZtmKTt3D3PZYj5Gt6I$Y{; zX@DHgBvK0-0nNhYFe2a3$wY?}shf_#TSwvyla&e`MWoiU0c$RiI%*yf^CixQSYr|j zPFnyJ3!xttJO2dq zCNA&c@|G84579Zma4ue8C$U_Brhp)Bgf-}eBc=!oWx68<-a}*-#q_cwXKOi4h957P z2u1_URXV&gkUX_ZO9Voie}V2ny^_nK2VKnmLnhOIh9eu9tcH@QXdt!8izzMCVOmXEMKX(`+$W5Jg6vOWWSlS%!sxXXMy3+>dU?#K zA9Z<@^kWM|ktxaklt*1v>f#s4!9EpiQ)ZV!2fEaMx!9)Ae+ukU=snn`Kj-=n_NSd~ z3R@3$tJO9Y^xv-7ql#gVa{brGCbbhe*rCvWutA~!44vm>j~YWUmpGWDY)+h;`s-_z zGV{}3;xLUFAcj!I@I8}v@V;(bf(*ibSY4Tv_WtvM=NqD5;L zV-^a{=UKa0FiW?Ys!p~$gG84RuGh2cW_G=rU2kF6d*F{D~T2)h(>MyqXVH(!LUD%z$Q=81|hPgJ1>`)QKsgRj9} z9N~EwAaTrbeh5pm{w-YG%@i>&%qWP=4$Y|d#-!(kOc0G>(3lqr#v)|u;6=-inZM8v zV{-L!|FY%t=PvU%FFE>{<*Sz*&F-#Rc+9a2k708{1gYrK$qZB$oFhoEDA?WJ=Gq`Z z)PgL8A;>~1g3McBil#26f_H5NX@|lG9&I9gJ1o#E?Y3f%S~Sl{&>?%KJX}n z4BweFAdB*I)_}sy&oD*PK2nQ>jSR3b$||qH6$2%EqJb!g53?hgMJdnxn77k! z5m5i4Si(PFOQc$3DSy-I)hh&nUhHkI74;qx-{HTm_v}{*_sO37RftU5Pgr>{wI1`e z_2VoLt`&P}gC^V!(w5JPgPoRBS3<^C_K%DiMkLd7%+(@@1EzQ0XuLC%Ium736wPBz zBT_dXWfk`MHzMI+#A5p{IyC#JF}uY)7?;+?JUcNm9GRAdJX4&EwS)e0nm|R_ij(Tu z4YHJRMg1RM-8B3s|Hiya*GXB|+L<*u08$0N3Bnp6O`>$=Dpl64S#Vp4kv54ycL%l( z5z#}~1Hw0r-N9jORl1$SSirxF!-%uGm&1s&!qyOc5NBol7SUPv^ZOuqH-{0-b{mHg zM0hKQ5v*q1$L_Iv_G*N~q zBFQ5R&n=>e;JHP)5EX<~6@)fo6$Rmqc99B*AVT!eWlDNhjFlOzx?H8CS7i_>gy+Z(Ga80ZicgaHWA2Z-cB1cG35n;u?70~rwq@ZiFuiOpx7I#LkNvEcZ%xLAUBoTGKvpur+?c46cwVYUt%q1~-3vY`Xx$*2X1Slr(fi)tI= zFlPh7by^~cFn}SJn^5Z|@r1@>Pw(&;%lv73*RXSU6X%-i7a2HL$;7#CITqaNqaHJk z4cmt7I2V$zo4B{YUS$^cGxz=<`1mAT(hGhr_&5^_n^B#a7Y&NiER5M$VQgJhq6-|V zLl*8kQC!Yr%q-02SeTh;PTs!fN7=l2HP=xVJZr3@+41Ub;?qKVJ}vHNKHUS{DKeHd zppkJR*taYkO{N0vi9lynFxCk+R+kueY*;z{@Gg(&KrjYW-EpvQSRF8%e;N=hz6?m4P*rA+VbU*J68a_3cgE3JqVpx;vaoX;#w{ z!>REIgRPqC4tKVLud_1jclR-@vR(G{(7BiKZ0Q?b5fI%B$U8$~C%@xbu zy^m%01j`PxXW7y(5X&+nU~qdZ)*jIU@o>@=yWX~sUH1gLmfEvx*%ysn)%NyyN6Hna z-nx%d_XMYw*>mdPFB+%%m=RFbs%3Qp>>E<|2%`?RXVf8IG)7f7rrbKL?%6k_?uj9F zh&`tc{i1Q|5ZzW?9}a0TS0=zd*VP{3*P-_OI_!(auY=l?sX!_mbj7O=>>FG6#MnB_ zo>zx|(Rg)~KDKrxwL~x$O=(egldOFX*FD0u!|l0t#21ZghetaC!Or-MTpX@#WW)+y ztB_)3&Op2>3zbAJu_7c}8-aw~Bc<3b8^5ob&|STWF1Gk<{`Cb4oiQW4G6f>+#)!m` z_JT2LZxRd}E-dOyFE)S=`QJ`qh!SJN_~;usyH^H!eU`X&ls&hO-OIVPBpi&yxv$vQ;;oq*Von> z3{^!neGe2?gUz2>#%fpvVp12KV|DJ`$FTzzP&>|^W5@4J9Bbh;aA7(EywqT2jJa9I zSL5X$@3RWb{b0M%h8=Iut^4og+*%flb;c_rS~L}?N_3?+FG#nu@~)9p@6pfkE}I;8 zgzc(rp!DN@#{KPicf#JpyVA@ln{6;O*_n!0bq2zbDq)U>(YenP%Lu;DgRn*urVx#-jGvdU4q0f4d%UF&FDQ3){Or2(StE;I2l$J*Q6UXHMM%yBc#EVTUAU zHdeJIlkqBng~8I+2Nte>}G*0e6Wz_5cg#Gz<>~bEmY3#`c-V z676gT#|&NT6N_m4+8l`c8W5i|r+)tYXGC+{$)YM+sT_#j(GRuA5r2I8E!c#O6o zl?WuO+O|qZaI|YfRj6y7 zR;7h>&l*_Sa^J$i!`Q*FJ?z|3L_#RYf`)@PwboQ+Zij>-rzn1z><*`b9hHG#q*9Bf z5@F5tp`XaK#xR6C;}PxDF0IS`Z;hmKA#FVl8bz`-(lnfx0hs$=Jv#-qqPhdg&D@FL;+ z1Zu7=qaK_h%UT|%SL5_jB(+nK!49W6_oxa^$HN(JR0=|1VJQB$PIgA8+PjVOxieoSF5tHKmc?8j=QW9M`2affq6w48tQgXa3 zM{H(Hj)x?ANRWpldcqN#EPec+iRdr<7$YN3h3T#oa@@txM=jF9CMn&2l2(NB4DJy=CJViQRMkzns}o@5Wn0u9q0NdW&qdg48H zismjIpox*plRhSMS5L@Hr`bCWB529AXEE86cqN5P7cT2@v7DPJotDXx@tsNJD^iHg z!rNyPsYhi>YsSvVbj}1{XgLeT$mPj$^)Y+BmRL4Q=~HKOFUuJWeUhGGw5;T#b*IiRPUpdmgo#e0}+_u5Fq5#gD@cQujEXeDT;yB!w!-MyLjzRdQX=QH5+BtEQADx z;pqB6BpkY<--?Ry3B^TGui!;xN2{|VQD>V)Ey!Nf(PmM3CoGxYykdRBj(#hvo+J61 zvxs`mVyE3?J$wpzf~_^gA;ahpR?7mMv^C7EWnuPOPO#Q;&4LwvFcwP~sg)~+b-t@i zq}O(mhuD8NM{OCky-^_rdQa?E)EZ-439GPK|3b6sMcJ!fZLRu(rui$@H&o7#gtchO zA5Um);SK%}ChCDyI2Nsf$oIg(Cw$)OS9U0%_Z4FQuNX$`e=ZGWZ6LE*ie$DZ&fYd7 ztZlR8=!JLnTUD(*Y!Qw22|WcEjCrkWJD#S-0tL@0OD;LZW9N7@D`H7il(rV{p6 zz*GHJSftNJ!y|PyECGlCW1lj!oP*tzbF$1hahO}Fq`y0y>hQM)LjGhT=!dC=yvwHD z)qmAM25=Prdt9Q;Y7923F{D4L5lW_5HP~UBhWXfk)xc=~6W$Z(71(94@D*m^V+@^b z)@+Dbv!QNkR&I7sqAgh0IICKh@Qzr#G7|0#rw*^#4N7Y$tAbhZVQvbZ!MN-{n?0k7 z9fs0gY?gMoo6`2N2AYKz%xhZdE^XJKaE3jbxqz&LvHs;T0Hzm%^0D7+9YLU?Z8qFkE zFo4)vs++3hZUtp@Y%{lVYGYhWZr~2tt$a!Zf9Q=IhCkGR;Sar;--kc+1`hwPx3_mY zhd=J^?Y))5pY-^(N^yK-J+0Mc)3EpHw%e0BHz`si9S$B zrT-|T)_w@+BZYkMw=r+pD4td^i%%bqma6}7nkEbq}Em{ zq|T`V&gpo&S|N30jY7VEc-i^SrtkR1JPYO-sDcgEQXS004VH#?JKqv|QNn@&Xu6@@ z;e-~^l1Zb4H|N=g1t_6+07^I_xiK2-NW`MCF0+s~JB8dN;W>j2Ee*ljzgml!!62LGyvt?zq2cn3hU*o?56>V zt-GSYmf^glKZf%%K3G;JI|GpjR^7}6!9<`Ne?uc-wG1D8TTkoi?d>%eR{VJt0P%wa4oeuKkUTKpb|v7C4!hq0V^9f#Rj zT^zOMD0VK{s>kvarO*PKUNx;!|)=7tZI(cZu(Je2EWBeZmqSJEg_C#D`_T zOiO$?e+y@C2}^v;&HNpOl$#Wyn-!w(DyGZXy3fQ6Ub<5uy32CtI%ezlDf($H2yQ~$ zGxq!cP>9mUImKAw!_ps?4~_G)u*8Qmx5Onrm@HTl#1bHuC9wpEWj~y?g(W{Yr2pk5 z^F+s5VkhCjJ&t1}d+Ye$I5rx8=XY#$f1Y5}g5`?kxJUtgt8r%yE|$eYyW=-1o=uaxW)s}$>A%>bey)r4aQqgu#MUmpc=strQ5vrYL?x62-J`)b*tvYP=U~ zNUN>t7>*{`s=HM~4x~tCIAtrJjBk6VNHS400q8D&%vwmzcw4?G05g|foPieyWv6ze%SR-PTPaT!!0#XssI1m~#!x>`voX(W1IHvdGrsGRLQ}aec2-9ciLYmCX z9PVXv=&>tWPHKsrv?!2FtwvNRGh|`X79YE!r7{qSz}Ovm?1EKGq5*$fEa9IUiRcr} zOltJRU6WaMBzq37o?K*B5nMeAqPe-NN4Z)d+NzKg&7Hy3L*G$|L|0D+nN{p2mWF!= zN22crnPssohO9DP>Bl@I`JYIo6=EMkk6OHpuw+K=T4zDvY58=P%D24a3l)+a z^ZgZgX^g;cH{P6$Sgj?+NOz<9C|@_K z{b^eHZiwESG-3wXlQg15SwX1{I(9{izeP)R#}eyIh1a5`@^t_=tN3g^s(V853DSvm4pTZ+eUnoi#`0a+>6GEjkbKS%&rKZJQbbw@?xKyFeNDr~ zwx@|sTJUWz^))mhf>q6d#5zCZFc^zQwIDW2B>kzFU)vCjbcHlMtlG3qEkc}+avcPU zl`w4=t={Br+hKpKNq#0=uNe$gCwbjnlS|1^9Y`O~2>YGu`JAMlo6M?$z&abP%s%bA zOL0J#APp7D<_MSfsSL)uuz8&27tnhbd-}ue2x!3v^K#?+&(vHywg@Zg1?;-0$T&g* z-=s_`BC04NWk?YzLyJhcsfg(2BBHrPq|7fO`e6~N^dK&e;)0+}N*1wb7Nv`Sck}O! z{QGpgc?K@$;c`AM7vO@nD82{~O8{^oAeJNG4~3-Cf+F%wQ-~H8k*a(b&$i=o2QGKw zau+UlY||jMAon@`%!8$tkbG_ zWS`2_hPPxN$;*(pkyYhfxRlef$}BKua5%c2bundwBJ(?^WmJ?7NR!_xO|dTQ+{A`= zeFru(=hGHElhkHNDh}U3ly40zY@)ttN7zVkiGu_pybuNf3;`%5V{HeD9ts|zsh25w zC@z#+CZ#4QGsmnt7G>rba(kab%KeJ2%rZ%Yu}&j~+CqsL3hW6*52<}pAw_gK*@cQA z8wIj5iOTJlJTnqPld&F+b!jN@UlVinIgU6+C^L)$7zD=p78IzVRE@P?gaI4twf*G+ z%dke9PbTl&M3K3`EYjEyez3tT2av2oa}V&Hk`C}ShQG|BIouS@wm>q)GV|=BFy7!G zjCM>30R>}1NWq)~9cvF}&C`m_MerTtm#qHie5_b;0LVop8vd>R5<=D9rj{oYgdI(P>zxivLVo_AFE6ubjX|KHxp;=qJW<`jazCk2!Z z*8OO(W{8x?=K$nAE}*K?FDkM`nqj6*ST;7gn_M#U)NV=%gV#P$48&efc!x-ezG;Kq z1r}NjS?El|m~~^=!QkaVhmvu3nWC@N8o`Iqk;cBYOh&O`0On~NyVj9;8pn!Z92n;n&;H~S3IMhuOFl}u0Wq9j_?tR*cHa)PnM zS!?IEuw+^bR;_NCyIKpK@)@^ac|uq*gphV6gfN32Hrv$IOm%NeQ3q41ge9nF4qR zO1P{6_xVf{`v_Kl2o!hXC=V(`4=L22yF;1a59Bm)jJ<%3-3kEQ%g$UvRQ8nDBRP)mdkwK%kI*RZWcDMxy5vy z?oQp<-@-V~UKq#k6GpZ@wy!Xzbr+P|0T$(!Om_Gap}4<09BqwlU~W}7Y>HPOvu4%m zg$r`ER_!GJ3LB~Q(BmVB{og00_bSvU0^swmGRNCX>Hd4WlxDGDGpkHlO2=5FG>}Yb ziEz>yEa%RRYA2HyN+AIr?89UKGo=68-7cH{(40tB+h-Gq#ZBWzbM7%S*6=3uqb0ka zy;zp-2C>|Y>yJJ&79gWI+62ro&B@Hyyl0M6ctBmt>J|PVJ0CBJye5%YFc9$v5?a6? z)l)E}rTt1<xx0l8Jc7rU! z$+P*YqW+c10eAAGg~rZH)3Q3hpa47Vm`)!J0W6@ejwJSf(@0|fLxfXELqylJ>t=Sn znq6;U*L#fYeK@s=`g;y41=1M-bVl&p049Bx1lU;ouxQkr!vx@;MJSKxqs9Exx|K55 zg%3ObtZx&Mf{gF@M#gu1BjY>1^IV3UU@ykIBhU11RH^BZo}5*x87xo~>q^DDc3~;x z2~$_@6U!SE)4<*3vly)5=a_tc-oqlxhs;*b6ck76@+)5Da2_XF4LKxe?94D9W&nT-&uW8QGd3&bWDc}bFN5BE8PQA?%*t&woDLkmqyXpull z3r#aObzvDZEq@-mdj_%p`h?Tn){p_*KKWVl|Lm@nlRi18jcI3pZJjK)m&QZ)E|usa znm};=FsF|pkEW%XR*6HoM`vv~p)KwTB=p^oSRpAvUcFUXV!f8gb&(`2IbV&b;vN^e z{x~0OKvbYpY}~F+6OCl=1F_p>3-L62iXhU z?oD{vZ<#rELE!YH9EM(F0>>;*rs2}Yrn~h+*qMezVVYQO=BQ<7Bt&CTg9AI@T%8hr*aou8mmq!Nw1oedu84+dslGnCXr4b1 z3MI5;(!XrUs@4A4{;5)y&dd5={wc$WDg!0|ltKR8tZurMfAd6@0amokXFL$8?WWku z{q9N^->Yx7J|{wr-|@%ZIyRH^{_AYeW|Cp_De)ch)B_hsEtTLj`!h2$_OF_S*4Lp z8u{nOl77Z}f}c@7fk>H%WZy(|Fp)BqNI8T^spQEb>xgI;5zQu|!w7lZi4Ny^-;X4s zqllEbJoo!zB4sHN9Zf{lNVHi)q)xyZ_b?()1JC+C6PdmnvH6zee?Ni9SKUR3g<#(u zcoK$@t`MDq+$-zwM*&d;xpF&+eE;wgMTvaBFC>Z)`TlwkQJhFU3QRE}$+z|R-d9*k zd-h!b950`Zl;Z5?Mf|&%fBX2i%D<7K9%Kd)`Bp5#DO&p9WkkM{-y|9gd@B?r>{O4# zIaNr}ts=9ZI^h{y_QRZFe%yvNv{*!g^_i}!J z0Z-D851Ox&zq1i(-Z^|4Qn+*YbfjeGWjlk2Ugq#U6Hxx<+740_%u^MG6t%)biZ6CV z0hN-XdJiK-r6N+w3%etMXiYUK<-_V4XE(OZt`E#^sGc3DnO)tc+TQh%GNrAcx%M6( zUC_u%f+GY_1$?8=@Qt>@H|mXV)EVDMagT4Lx5qaU?BlzPe-Gy0$ir|G_PQ zkp>^%7_9J(0Sn(4wD64-`1l4N;Tyq+_(qa2d?Vv6zLE77-v{t-q`b%9NF0XmGL^3P zP!Riir;pEn)}oT8$5(C%Jb3RJx}i&Tha0}aFD;dn9vmys%|wPOH{Q%UuXXFn;Rnxdvl zPdNF8AwHGLt2+b1+0`4Wr&n*Np5~8tY{Vba{DFG@U8{dCLtP1mIz<}l27Z7WgaIzK#|AjX z)d1()H^53=;omo}muk^2pYN?^5lzXfF^=!DSX`I~_nmw~_c7ry%zHxR<9UJcY-1U(%^+(OM zr3E-g$uMAG%0O~qKf;)O-%ASqfN}kAFDW14@RI-H@;_WY#^n<)sl~-OQP+n{70NAY zz9WiAw-!d@@z?@V3&#|Ys*Eep6+dQkv>$FmHTF~x%Pj4gfVV&JlIme1$eaInyJ1zyR%hF2^|p;x|9Nb*QLNEe`;Dp+TB*=Y zE6w1oG{d%)8f;ss;q%x^qtmT48m#4Awy;HPts*zARmWRPw>zvNH`BJYW_})9YfQSe z#<13ESuXpLAMVtI@W#8b6P%H8$N^V-FD|(1%tk#TY;REQL+S$sFKI z<|V?RcCB*R+!j>%JtLu#m;35Eh?Fo+gX8Xj7%^WKTdu@tjkzIQ1aJp@m54cX;qCwc zrxs4d!#R0Fd_?NV5RvL>$0_PVF;5tQd+Xq0g71v^%n(xwH<^;atMHY1Qt+#F5&16D zh}IMNt_>1(6Zw8!O|*eKzBUs1>Pxu>z{!~&oSdm3LbbQIx3>)k*RUzYprOdQ$XZJO zyPeY7P(@3XqoqoZf~!CgTFMuxO~ot2(HgYV!OgYL=&61!AFSCI(xCFf^?^_<37##| z1L4Yr4k-bdNls+e$D<(gS|&1o(9d~M{z7_~Ko1f9mI&v)sPs3~{0%_=z~wDmo+a|# zR>%&V@u5RL!OhiZ*p|0&Vb(ap67_x6+zSs#y9B~yV!L`x>C z5?%j93;vm?eB`X^y84>B8TB*jXI0lV%&4!ftDW^SQMoU!CD#QK_4ThH(K>62*O7+E zf(XsyTg4G8LIW*uXdspK!@}5-6=s*54dnmx!%e(b_36;vzJ_G7scd=0Z;-hH4+x zTnp)g{R5W}^O7)YCvE%~b`LXabS`CFuY>mp#5RK1B0FMh7lYW@#-IR_%mQO{3yI$H zk`Lk0Z+fYG+G$TWzVmZ&*2oLscLHZ?!FWa*ky8rRKj324=!QzM?#RvouZXG56Nn z;iajb=GwRQuQ$D9Fu)zdNO>3T1ih7?5WEPdqtw}*qE`Jh%T_>M4l#WOz3!c&1%*CReXcyB#V$RfN;Z$EB6>vO8FlRuRpWQTvnjhnd;7~B zs$_JBdOn}-P=Y%&qr*U$myYWXhe1u_q6IVS8Wz?!*32>;2D*;6`b61eZrsblAa+K! zLCk(i60jY_0vN>B?;FH&9K;6R73y+;%iszfm|@N5(hr*3u%`6mu(pd%(7k0?)19EM z$F%YNJf_Vx$FyQL@2GFL9o5FeLhFtMgKg~xawjBK!|}lrtoY-D6?FqfX!ZhXt}WP1 zO5tWwJSUS{tPCa9<7E)_sD;Cak{VY|CZE3rOUXUuzF=E>Wo>)MX$3=#na~mo4xfp` z2OLFxa0~*D`u2{~Dg!~FF)C(7RA?e92BKmoL{SkD*2wj?NOVQCYTh0v@HRkue3`>& zkCQnp9-2NyAv%GYYlpAE!t&r1SggTHc`5rF^M;ZYqh!+sp;+UaBO-Y8i>T&5tM-DM3doz?~!cjzK2cF3rVMlpN6zlR7+JR zwNxq`ZBOE-_<)Oz?*qYMq(`PG{M(2@@$$ccsym#}FsDyO!)+v{?WF zYZZi6fK>_*J5-DdTkXZs#PIp3Ba4X2y|s1ih`or!+AG0LNkn8JXkj|X3g5p0qpb}X zYXJs~4qnOMFH>;8xz@wd#VBN~10os$VT52Vl!!&;C|>v`tgnNN?dxcbzOSQ%wy%3_ zUq`{MuY16X1?=^eQrSJM1<@X5)WgCc;haGE3z%FK5|xiT1d-xe==5MmAlj~lPETl^ zvGrQWe+WZ}h?Ph%l!|o)J1XOWc8&3X8}>m-!F6ug4gJ_12_`iRllT!@1`&7o;JXgo z;U}yj^{5_?pH#)`CsiN$l3K7U5l(F^@Kbq7+Eau;obE_46c402f^9}v5^ENWK^=jp za2JdaFsS2$!O8fp)_D_sj!s}Q316eP2>vWM98q9)yBPfpmhX%wVjDL0ksgEf@m;ES z7>n3Ki$%0h5>Y+)Ac_Ycbf6I(b_BZ*G3imkYUQ9>?(0fwiOPr;LP!`M>8y!ILzCU% zRIsDEG7yR2jU;N>n$!~OK^~|PJcJLv$MITvh!oT=1PMkq1BhZG9G{*D$Jc2a@l!WE zfJR7Y$yj8)mYAMQ1ybSQ3Pq=SBBzR84sjT5Yrv5IFY)_ejb;v`AO?)yH6#~BTFc)- z10wbkAJpo24kJ8j1&7hN#(jiI8TSz?wT8cga47>14h>(<@0SzdOicDctf&E_lMFl< zB8~evd(psos6cln5et9A2f=0tg~JCirfnQXtf>KGbTbsCs1U!TB4pHXoS_s(@E|yK z^GXG*jihNS8E+suQ-L}hbPyQmKwK2;q-M^+V+~)jZyD0%wP>kOR@C?~sWefKv!D(| zlU41pSbIc+k{z~~ft8_X(!XTI`Z|A&8yW>{)bg4%Jh{=R{gPchFdUjqbmAjFVS}m9 zq@l<(21S!KRb5dnRn^U0t3Iq$S1xE-)oh2`+WaS>jZ_nNiP`e%v2zzJUsc(%WV8OmZ)L| zeN}?38x%D!S+;E9F)Q34WN67e1M6#G@eLFSZR&xiXUL&J4Ej9(u8KIy{ir%iEf%;A}uuwS=1g#1lrkXLd)G0 zk9D};#MCGkuSoB8#y>4?(6MeQH_?qX3s$0cfho+cu(85TGO_v7*mTY_rP)0TR+!lK zH?fs=w#)qDu5_%f2b%cCoA^p}7OYHY?X2Y_K4E!OxWR0Wuq6|8Y=@ZG4wXBiG!aY6 z%qNMnBho`nq;q7XLp!nTm9ik-n6;l3e5gmAX(FB_Bi_%jJF9|`SXZbm5=bzuRuznO zqD4l{$L&S>?N|p_b}k4LF~W@|;hFtFxVFu%#*zk9Rjf<*sIyGMvt`0%(B!9f1wyl` zq8iIqHgrDz5_GvO6-gIf8IQ+7WwuGhmn)T8cmT5MHO9GfOe$WP%COjma43A57Lpmx zI*Hy-GGl|WXj_;~Q1H2hn`!vIg_>)}u!&;{(JdYtt{c

    z@?lc~3yZiXnQ_O7FWd(0*&zmM3(P^lWu%eD#~v)MWracK1+{d#S>e$Z}7bz zPnDV!R|0=&S8^;(1*dB7dX!Ss-O1(|ZrS>XgOK_X^SP$z@h@DnNi`Ei7@+_)!juRQ zh>Io0$}@U4P)^5Cxl&>xiS85h7=>jq#gU~kR<5m4fdJqgp#uSKOFX@aW`Rdnw8eXc ziOb{lAc*%!(cPMDMth|waz6Y3=7(=vjRv-Sv+FIkUTT8gTHzPmV)i0HQ2D~UrxH*% z&=t#D44A7&3-@DUn?s7TV5DH$0AJoH3sbE2QM?9Om`y5gm4n7Y+6$MfGq@_PloAuU zoalVV51Y$HSBK+W{EoBUt3_5r^o|Y@;jG2Ag4gqEQ)lFmlW^NVcegn3v<(IB0eCg8N5ru`>t9@eZIbNj_FrE90-m-KUYnu=2W;?4f z`*R4Xp)!o$O&4NsG5WCy27)A9+Ed{u)`D&GOUQsM1VCQRx?`8`XYA%+HA7ue%${Xt z2Jv+!E@3^bjZr1AHDc3_6WLSXxjB}uIPnY2Ou%-IVH~`8z+8``Bd1_&)zvZ0Jq$<~ zaYN|kaMH$UvsB~@fe~n*C?&(h6!7ii#aErVGS6CIc8vh(k?6GJrWpMOUtKmq*%!wn zEr39aNLlZ!)osURz4(BzVI7P>Y~T<}QK@az#LN2X65jx*^25J2()OH|V0qo7w?4WVY7=P@ESv zQ8i-Pn&hGa;7D#kF*rO7W~UnH7KkCIxo`$8V2)aB=-6thPM!iJ)lyh$JzNylT&kAn zkx4dDAk3EL(whu|1}b$jNe$wc73C<4@yggL6aT=Y>kU`4D+`LPb zjZ_F%JHTn4ULZv44|tbTE)>PPxC7LTtaxu4RoWUZA>I-dDo&=XIkm zmgtq7a^?a}b^Bt;Ua6!xj*{2kb)-t3!s$yqhzY+)rzzd0LKrmc@R|0~# zv7krLWHVX~Yr-L~PDjzqB$fv%r@`AKP=`-Te*RA{=?_e9GjxdHfv#_1v?%;m7am=E zmTZO@equ(Mi6sX7S9v1s%Nd?v(w8|m7->372EH- zr!C#xA>`Xx8Qk;aj5#3`>PmOF`GpFK?aD0R64)2Kfk0zDp>izRMpe0Pzg*EQXBoIX z-RbV6pJSU2xLVm96Fo!e?m;hGQ*5{3_uf62?jG_obGohhc|Gmvet(#`qG?%^GB}J0 zMN;Vjp9*=6Vre*)?&(kW_@gR7uN>MQvDJc}FUS?M=qhP$+tU3$TEN52E@6Z))?IgddcX&ysMvW;Hf;!@B&)iu7R9F4ru%)Cp+#*i zTV1X_J<#sq41|(^koI(s&sQK{Wq2z}){QaQ(hw-hzdh~g?zLVc;PNIk(w6S=iBd8% zz+6_rG(=$A(gQw%cmRz6SNTMDRNZk*8>bHtXE5EJ^7?jE+bk9XReOZ0CB3Lk%9dig z5LidfDXIWPe@A-2XL42+zQm%?V|RL>-|vyOIj$SvzJ^UwEV-tUFAL50bO%7O6nm_w z38N4w?^v3q7UYalESjc>=Ty317>(<3X#Y^U$EP-P(+aboP@tf@8ax$TnUv`pN#Yb6 z1c3l{fW0j|$O)BcY(1qyZA8iIc#9N|fBYQ_$}K#L!YgY#q;|NA8nB;^!l8~*F)52d?(;?$~;Ovr6Q58cC}XbVr28qN2lqU@ftxMgc% z;b34@qpR6L_Cf(aI@k?iBpLtlUesq`tHu;5T%ll}CTuU5R>N++(=8-R1Ff2`S^yYD zH@slO8j2zDn&B20Tbl%^VObqsn;z(fISnKaE~VjkH{N1eLy>U6$BFe2SUzc5U{wy} z*K$S)Ec0T^V1x4wSR4r8N;{}Imc#EI^-#zJI&3raiPVruH7s5n;lQx|0TVfn z2I1Le7l#cDV&+kdPGo+lD7d{)S_lRSepu&k?|HxP<6d^!NZV3lI=Va^J7vYGP0gpR zY+2QNdf)0Z)@)CwcbxyJJs0l%G}qag;#AH!(jF;#N}?Z5DNjiZ;a4g_zmoJTMZenU zS3CXcpkJNz%Ui|p6Fnu>P1Aem7i~Q?K>sy}Uu`t8jV89SL<&ILFfHP(d92xX3RnlN z(?RQW&^jHoPA4tWMT>ONB3-md*RUs9{)g_WQ?&9!W6$9Qj;I`dYaNMSeY(IaQCpTD zO9#vxP#;;xiXFy<_NHw6&6C-t zoD1Of&d{b&h$&U1SGD*}L~s^c1$PgM6-|mNmfq@WMJ;bDC3v(x7_~#}Fo5@}zSfqD z#mPa_FfAUUkr#>;WX4n9ii37HredcUL|Ag!9lxC4-ouiAt~#?jR8%_m;zL79Mx|+Fszs zOPS`*BtiVXIVvg4!J|s=015<4jVdt;15&{U4-mw1z=&6)-sw^sd+Cmkl5!fGh!9AY zt7XwxLV}QzhHFWbLSUBWVTa*rQ>N^CPbvV)Te*rlJE&{00F0KgK%Zf<(J{MY%0C!8 zM9oQ!pP&T>iOtpG!J@8ehC^M)cF3!vMXjP0>HA@}MqQ3QTkT9#hk6+k>;|B*V&#eM z&Y;f$V3!I;!0jeeM6HNdTcZ(AO+(tUbr99y!F5|C07hc4q6KiGyVFN`aKdvD%BGAC zlgunFd2CmrppZTjGz8)mx9%;a;B)OvXaf(ngh=KIOTLJFjjVGTZ=KD0yaBLWf-6qoB<(tIdrpyX6NHyE z*)13hN4OEp4R9&aH|=pX4LvHT8O_ro*)mKu4txa;UKRH8Sv(1rkFEjmin(8a#lsLA zpzk8{9@?vW7}4BB2fl% zYaO-(3WPT_tks})!V>WsYoK=ZwNrYPI#37>C)S!aP>4M(fWk;XZ7BGjpCiQOi5g~9 zicV?{8ZpeWE30;qI}|R*7Ll0jjp{&*o|vBlS8GtdMw>lyG)3V(iayk*ypqk_|3++^ zk+D|eG^=*=_=0l@OY|{=G3|#|;`ZVllyQ*els);C`zCr76C-=V?G!jTLAGXRCit60 z^#|DwuRESfk`L%1Q$?F|r zhXQ_sz=Kb2E5vW3IklLTk7{|`HO*oi(N^R6Y=LL+@$0PP%9i35gyGHsm3=YLP5FnI&Ak1OYp6yaBhkUqWulEvfEft@MWO4pCMa6*vV!U-O z$adRB7NXt*oUfZ^#c)!z8L;m)AFY0r9A|_-8)3s=wu^mDA`ipZk%8e5OlYn)v}RTd z!&+nRVNW6OJ_Pd7O&xryNJvS57Yf-s=K@iLdJraayO_sy%H=dmB%Uuz4$iQMQd$_^ zmiKwL$qQi6{9z2Af+}tfxu_5%v=CvUgN5;_R!1Z$#zJOz5aQJE)Lvh%2)j-uSF+}~ z!5{K~fQU3AF-~m8OOi~}@TqwwsOT+uE>Bo0*BZiNh^kmK4XY}SO;{ERFoU*@K_NKQ z;xisWp!rK?PQe_P$`(K6^)EYyq4b62sJ8+I_V_5F!V_sN<-BnYo;!xqV(^YN2e5(GUY|sjkj$M35k8xwJ$D zoW9u0XAt(s0Xg)DnSA7<;HFXrFrRuzZV$TEwMPmeh%j;{2B#9a6<4lW{KdH|VE9?Q za5)P&E)5$M-8PMqX1J1C)D*i_+U7t!7Z${R*r+hCysdC$BihQ8RvNF|&-Dx#l$2R> zOKI4s9K>`)8=#Anv(2U+AFOsbwWdCYn^N8ns4M_raI@ggV5%8JLr_QYbpzeu4pR`Y zMblt$^u04;m-<4nt;5DV(So^!|@di5BV5~n#ybn2<{N*qp3X7 zJe|Lkx%~0-=WP5GMs>~!9p1mWH(y18XYKm7^UW-CauZ>-Y~64@7N=(QgA`|jZi-bD zTV5S))wAAfE!AK!T7}8Wl{}Bs0kfWG8>m5`A=4197tM^*fMjBOFL2$(=b!Wm{x*~Y zMyPU8vllO9+_u>mt^oT-gD8;p1mAg@`SB-dFKlyIYy9=d=&0tFtyp8DXMGp2haF>rx@@J5YiXpm_hd< z+}QWw&oY?lz;4RS0M4Z2YNfb`S~LgD*b{XV<=y#`yt)|>>@zmw0eo1nKvX-VI%;x! zr0*XX-j0VX3e9q4J^BJ1_t5pw!$c^@Zj{d%I?315Cn;&&UMbBK`Cu|K9H7Tzx8aIr zPfA0|B;AurYfU@Y|KT$m8XyAwSMgjm?SdRvtBESct7bDvXYP@G$?Qz1Uc3-CGpbUQ z_=6BL+R}PyS^oT>xJ80(!A4U7+0S3K;mw6Ca8ME)HT=7&xWf=iv&*57OkL{wZ54b1 zRCt>cN=K<)wRmCmev0z~o!%gGwrEP0Mp=Zl9KudAWg%1q)l4i)7mHE*@1L^qi!-EdCELGzwwH4IW9j0T$e0d8WrrJd=yN1~S#SjIxt= z71;UtvXRtDWO{#u97iY^t6=4E3LCUZXMM>sZMU9G5tk4$Mo9hKZC}?TWU66%iI4`e zi;())#v&w7NaM0_wOp-4jSy-1vf$hBz=WLe3>B;3;l%(DP>9MGE>TuV6gbM504ZB~qQzC*V;S>2!P>W(|KK zX7%EQ%b`-$W5g}|ntESXYqAGRG10^(1=mq#Kkq{V!J{v#eX|n?;MpB!4_{b#rW4TM zXOtSI?K1|xWK>gx(9JfAkibQ3N*8IefE)5QjtE-tlLRTQ##aRnQP4=%AF< z9L?61B3LI7jajXzmmt7RA3Pd`4_#!Piey^w=$r$;Tdks^8(ka$XYhl(UI(-u|;X8Layy7!Pj&Bt!jWYqoeB(`#kO<#ev@(B7(&kb;=e9Wi2~f zRIJsFyk?&bo57Kx4&ZFnG%9dTghS6Lj@H>Oxwc|B;49l#%67o}KLu?<@&}x34qJBM zbqaWlAydkBQ0r@`BUrA}8SacE@bY$vvJ2o3<32Scr^m zZ4XTxiV$}6!Ol!LMr11XK>rT-cZ98f0VWdSS+YYA=~N7}8E*Derd1qzj#Gi?pOMrC zGY;ed{2k=R6mUbURp#tKO?KYq!86T*{_1Lm>+~V(L9G^P1_q;sy4sdgDnF~_zZB*? zw!E-IX&49C5(RjCe#9n4;pzuZrFw{#tzs->Dn5_%G1GKHAMZL znS2=GsM-gXc||;H4=4k`zK2if=H1O0v9=hZ&Pa93{izaQqslIBiRR2 z5->ugYZh}eSopa-@$oYPNWd}%pNBCw~NXHSEqkt~(0ToI_rT6SCXdPUh&00u*P@4%DE9CdJ!9Ri! zLN$H4Xy$c;u+My&?y43~X@Hbc#wjSa=J3RNnh1mprZFuwMhJ-zLcRrm2qAL_A=khk zLP#AUc? z72n?4d+Q}v=H^F!bLZ5f31-|(|ql^M;^cO@}qxt`FP9c|8&Q`y>;DB|JRp~ zX^Z~b11%%-rzB&;t@a-dv>$)YEve3?TfUiX?rdNA{q2c@{?q5Kc=*AMn_fKjvfQ_n zjdL!1eg8nirTfT=%Rc${@7z50)~9}W!`^eQyuEYm!FMjYx4dotzr^l&b=9zP>87LJ zIPQvz|LG%t`}-UBCC}S?!!>h6!YreNsq+XkMr9{$U9r&=%n=<_=sy*7H}se696{EdC5SHA!15hot| z%B^RYR^0#Xo4da7)^)$QbbsWGh65id$O~Ti!MfYddbfY`w?{sH%_lb*@7(m}jm}%Q zeV)8L=f%fwnEQ>&{`X2RJhc3=PzWje*@Si_B@Ef!LFFXGD+_D?9cmKoiH~;*|nj^2?{mS#di^t~w`j+E&-*(+? zi#NTzhweOj-@o6y^(&(X zF8}A}yT>-`2ljt!;EnUw{qp3S%x8&v)He8j*jL!c6CqWR-U>DE*`FA%OsM_+x!mO0iqej}d29(D+}@c{#?~Ygt!?;UH%g8MFURN5nWV=x zUwZMy%G3AkXkM~(S1jMOfB6evXgU7;*MFd_{?7-0^}RR#&z`F;{$bm5Z+G2!`j_=3 zFCG;iIdR_Hr%(9h*ohZC{+UPr^rvU{H4NpFO=RId$ct z!slDBe*Lb}RfBcE`tA3>GX9I#o-r2QepljBvgqb>AH4U#JnQ#&tZ#e#{41{hh5YYN z)-CzsEpzK{d@S|7KU)9)rnASjbkBLuR<62#pmM$}*FExf@9)0zOw(N}?w@?tT)u7m zz6%yqj(+Ope>&sZJ2%8W{^%|9PP;JLIQGIzKb`a4dv^ZEn*Y1!wN3kP>gjrKL+_89 zv+w=np>uw6$@SlO=lP2YBgqqP`3HI6nspa`?!aRWe?H@-IZIDo21|rfkS$xUD6WRa z3%URhvIz5BEAD7^MYDPGVnT?UbFG~$wux7MDP-76E>|?iW$Js(>p(YNmJ1%ku2=1N zo~NsFUNbaXaZNi^KU%X41Ul7R+0{x`QE~lsZ$-`0wlY3r4Gu#91jn^CrR2eRT+LR& zaOD;8Frce4J1FNEfTg_bWU7z`Ycwp-aYa#}41AKpcan^x<`Hr!U8zCP&V@C%4$dm( z6OvrEOzvDX@4Zd?<43*t^?mxHSG)$*oQHm>Rw=PoQCAo*s*0irMS!Z~x~&x<7DZ9d zd%A|0;TWdrsT|PJcv02Ig;s#h&X{mcf|Tfq%o~zlBwX?_0=7>M=sd%LH_p zDYB4EMgAWl4QqZ6sQn`$^~;tJ@)}?Yb(=Q`X;}6UA@v9567q9G>YtrQ$S)xK5%}{j zgw#(@Pm@OpX*m5?kn%Vo4RuezpC{p;{|bMWk*UTb05X|QrzEI@$ zA<6kum)tOM#pjMDgs^K|c06a=;|hd(bbx1JWCN_;)b#Z9k?i*mMH_H)nKAsW>}JOz#zx6O)wvEz(8UFV2~xW#fQm~aU$?4oF#dl?y<4hn3Yp` z1(3)%cr&Y&b}Howp0N=3droNW1i7n}U2|v7)^_nF281_!;JY5DIf+!s;%d>(76_Eo ziURvE{2aqXdkMlH%W(2$6>P=vumT{IEyF5lS>3Ay-Fb;s>mm#?;}+1Wj=Ngk7Ywpw z6`hg-=chasddS#%Hm?bb3*e6?%B7+|Awj(GWXHC`>wGvnYnBwqJ5mI+~VOjol7*kFHMc09QRpaMO2X3DPXHw~QyQ(*YxmJ=!m!*?c~ zl$_1jo)o|ZdOVm06DM0xt+)-YGo7|s7W5|2a6A&*N>(?k#skc%Di&a0EhvVg6*&bc z77SO>4b6`0B_*%n614y{Nm!={2`o`3MIaqKHKz6x=z2eaHZHBhMGZ6-KoKy>u>{sn z(y$vA;{}TdX;^v;A@!Rhgz%+n2`rc0{B+!(tNNg6m_FK zQ4fW{@&J7_Mzf|mrrE8!8J{%EwmBAeP1~lc^eR*=-6IKUJfZAllAzPjAv$r_kw+BQ z*3Ubhkj7Y6ZBORfyE_6$&Rd?NhMNpds|nsv%RCMtuxUEE9{Y5P1_ztjha=j zxz;W~O!Lmb3D!xl1;3Y}9B_07`wh5S!+y^tgtW2We;|bP(q+5>7W#%c;MlS#Zdz{K zb>c-c4?Zo6wvO)HxcSVTXZLSi2QUKG5UMj+)j3eL4yrEURjG0ZwU5|3x^r;zrnS}8 z*Rbk!P<<}C)bQ$nVmKA!-EZBzWy{W?^;-hnx3T(jIh~=2x!sAL1XNqFb#&+1o40HY zR0*w9~eM27yf~W zKpxFcOeC|N84y=m6 z+nQ*FwH(COF||OS0~s4Z#z`Hmovm#WuNZ;Wl5%2QO*E!zqj63(8dDz-jo1@K9f zkH)qtG`2A`&h1DfK1@8OBMvH#Zsg-y#qu;ZXc{zVBWu~_#H6>A1wB@%QqJV9KsT_nK#j_> zP@{8PTd`#Dn&7~J!e%J0Rr1CS>SW$lEO>Dt?!Zx79AW|T3N^C9p2f3au!iQ2E3R7L zX#geaa8yN!+tkgg6Grvs^z<~>3E&$R@Wo^*G8fNErs^R-LP*1ApxEMA)8NMS!<)A5 z9O)ly#&rhd+d>-LVrNNFL0apUqp5Mr@it#nuN=pPf-e*IG2r0)K3uD&FNFi8=}YIL zRG-fz`Nf0~@Xeh=7Ljq?$e0syTWfn;BXMB|@8p|kV)H8MxawJUd%B?kt`&lYGmj9& zHt3fC5r7KHF=*2B$aG`@nXX?#rpO{PT|YJ5Kt4*Q8zRfdbi= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302174004-Binary.backup b/MikroMaster/20260302/20260302174004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..bd5fd5cbd5cc2f22dec294b0cb17709bc2bbadc8 GIT binary patch literal 289184 zcmeFa2Uru`voL;AfFyt*ARxXX%`UK;o`?kz5D`Sch6PhL5GlbVG#i4VSg~P6#g1ab z-o=8wcSS+5V(*Ft{?BX@#P0iDfA`-1_qh+x?#Z%ecV^DaoS8YZJ6Wq17Un7G$QU7{ zOh{0vV$Bdj6ogOmZRegmZRfg3aVmK%n)KCCaQ8qEQFlt@@QEC z4I!jX(0Cz)plPnZ3B6X^s8$;uYq-XwR@<9w2eDbGiUNWQ_7CIQKTH4< zS)3$ZsgTGBnIg)7Sra`_aBPBt*ygB;LPZFfpen>dRfxomf)Jy+y1JS~55P>0l}ThI zb*ieXt8Mi6fTIlxVpC8R1I`BE*QVGJ>9r z$rP$?I4LlkYC(4C|Rx45`Y>Y^~Hl|(5b501RkVk8uBTM#MoHA zt^>&>HINxWhifvDj~FhwwfY!KC9;^r1Q-+zp^l4E571-ju0PghU!YEu{ycD@p$)ww z_2+@}{Pk@HLMTq(W+H@A_3c6`LhdMtZH!Pp0yY8kbTou#FzraZ03~BB5gSivL1w;l zF%XiREh$0 z^nx1zEVSh0WJ^><9)IgGK%<{Nh7NG8VSM!%jV79Wj7Ae3S%bG;o^*sF$JGRY{SgAj zaA(s_@bD`GI< z_A;k0Z*QEejF+lX0BC(P^g*OX$yW9xr~m5C%lSwk#+n+1AHsU~6xjYbv?YUp=# z7l=TtOs-WW>iWRurxyb_`k^3pJVKN~Ab^Mz2Bbs?#emL3h)E$3VlYe)QoxTW*r{Nb z0K0*pT5vXp3&NPFA=CzSHcS5m5ZH8m8`RkpeH*Tys&9Ky5t@a9*p{R){(}$&2A(9G zF|b%8gc#$QlOs*_I>!njCe@(sm^9F*)|ym}mWXqb6ADRUtkwxYaYhJtt}`vV(f)`I zGq%)wo48cgtL-{>MQWp&4W9TV9o&7mO@Rw?LI}6i+Pb;k*>NE+sJf}BpV1wXU5zC2 zIAwf#4O}q4=wZ_hDhZnoCX3H7f#B+3LL>mzuUd+lSi2p{cHcBKg3)Z*Lo3!)pO)J! zw)f|BKFIGQ(E;FGUVLYunK-@8jT19l*I6(Lp^Akj-b%Nq3LP{_ zpAsiKtXdduHzudC*(tRHK*P|fX+k~qdjNe!5m5BxC;>ntx>}I{kyAe?9H!A{fKo@i z-nU|7OV0}f3I;t!&#&2&Zpqb@>J(^@dee&5i5xl66m#Hr*2+!?06T>TT^n2UngMhN8_ zAzKv0HbICqY!E`E>H-7DFy|m-PHM~Q>S~iOuVs^(xw^XA*l;aFf$PpGaAU)@dR++? z3**c?p&Xdqh=Ndads0qGNoYh$D#>YenO=1eLeeOiDqi6kMZ^S=n(9RMeiWNf00`6~)5aWF{kfVy6p2;8Nq-%$eGmL>VB4-u7 z_>=4f^ov$$H3=%MXPiVCZy2esNB9UrOmi4v!^IkPQi58gFkHVv4?P@Lpdj`fgeXY} zp@|5gNeEHK0fgDGn~V_CIvQHjVK-B+H)nwibff5?pAG*}!@s0D z26p2CqtOUCn=4`^nrKfwXw%^IRM<^{-B{RV!7decwJA^=`Q#{N0{s4+$)YwLfC$Q1 zk`G~fpr->IAD|$1ebR$~iJ=!2A$x@KsK_2gYqbetPtWA!WDin4waOR|nJUh+LGAyj zRf$?cEmcX>a`K;!q~)B65a0|HKn--t7F0jXKNJN*lzIqJ91vo9IqAvg45V^_ohvyr zR9DwQh?xQ`L$QXP4P0$t8m5k8tbkN?b@W2cz<u8d zJvHEXMQeK!z`^s+gy*fJJ|z7 zIxZnrk#J$&-qMG&I1@PGN!;X6e}r zfM!t;Vw%C6N(D_#Zx0+%3?c4A<#5VxrH^b(Qn?ylxQHFW`tI9cF+ItjhX&Xy901 zPdXq8wKf4hqoR>0;}t6S4VzD`qt9oCBEhEu_#=SmLI9t%G)eyrbR8+b z&=HYe8wsuTPlID?-2_OY023e(j0w*f!O)K@ID#;mq+jR^^Oasr!OR6w8BcklQf|Nm z1_w4c+UxG^48L&}q9IDB?1%viSpXi{Q5LHt;^Ny{fLRZmYWkdR<*z zE!4N)R99EC_3eCwP}|QGW1M!&7Q{*TqsWyry@Mw-4EwVd%`R)ej&taJ#dqTeD7G!@`5TgM4*8qE#Agyd;hQ zo*_}y5b7jC?WswW#uHi~4)Dw}Jx0L6b@lBn#y;leQtN6A#_iFeHYs2z9BS(%Jk>MX$Za2w_R)jh9Gub z1U6F!X>x$io28Exj@6qUFt3b52o2MZ;c$d>3T*<6Avv9cN6d0`B)}tv5EN;7Tk4Ob z0SM!332rh<)}Ky+C>v#NWGWaYEC12;0ke-X6@q-E#is#3D+t`0ps>J%&vSGv@Io%^ z=E9CtKSQB41R-Z@T+9`Ug$glGA{G*2f)GoDa_HMBJ7Ut4{1<-|<(QwNT>l%C2ccrw zFH!CRjxJAt{VvK@xLARS<%C#)i$%CtF2)HG<7cJMr4JW=86R}G0qor_+kZ5%n^`?(}&vfUkm=MB>R6ovZNBL z8C;kJzQKA)>;1pPnjRDo-s5)>w#LOcCT7dUTwKhSiP@M~#wIbgboXxMwD0X79qKke z#~9|iZ!qp&(LnyIab|^g4eJ!p!Q1Kg@wOuI7K&xKScr>xA~8>)Lz}TTy?5m6KZD9n!)^XCtlu>{!cwjx^XW z-yl6`v6tdkWBu=CTF2s2Tr5|J36WTiiRC;U+J$8mr!O!lf6^jR{TyvD)xJSH{X(x_ zqTRq>5-Ukbb@ygt?g^?`_raO{o9RnIh}mKuTP!8S9EBLyOs@=H;-=;#|37~VC+oyQHu{5$@(!D5Yz7b6I?Ma6!WEGo>0u;iY2;H zzHJ}Vi(6pyM-^P)&rt?{@*9+|KX3C(-nN&-%hf8S++8Rq*ce7ABm`TI6Vl)2bt_zq ziP-`%&I4OUBoIq<0*;#2^PailwqCnY{+MAN^c}mENv$#8z?uGr5KCJyf64AfvB}DW z-_~n7yZk`LOQg6^oWCEfHd}U}Wi#mIUDtl`j4e39$vuCTj$- zg>HFEKXds=3L=-3KF1aqL1BL3PCO3`Vhqe4-W|J!xd(UmA*qnH=K26pI0PB2aj{S+ zmJnjOT+GMB9FdsE{Yl*6n`=o`r@P%BAq?{?!bocfGfhtzW({E=Hl!zv6bRE#Png!V z2^04V!jMbu?y*EXNtnZZk}e9Ap7OX(BhjB%d7ZyTl}WGBcMt&l2G7ZD z|FFAC4^oErAaQh3uQ56EQ%SZsk1bb&sW495Z##MUib+ag4bL!8$pt^e|v8PnT{B3)ZkgpwHj2)(4{?d`z*2)AiwcSoMaC3npr) zzW|oLX)ffdw{C5U<>=V0o-R0yoLO-ajh0Y%?Bo+d#)`j23X(LGWCAU0j(Viv=!k;Y zkfsIcS(X-vTwi3gqL8a6OfoT});bbU1(HuL>2CnXOJvRr3+&2P=kDeMIh^5@tKGQ!1HIG!P+1pQ2sVSjbDU z>PiOM88Nz(v}j%TGe9&T6`4B5ge7w(EQ&Fzs)5c`x~xqaxlBc9qX{+cjGjVw7^3DqgEr#d^w#B&CedqfIX3$zoNBHEVKx_5XomUlauP z0`MqBt6NrJ!kPk;lBFNZmHJ}_fVmJJxdL{O{sB1=&M=cZqmi&nhaH&!k^n7OKTJ%B zPlz)t2Euw1Y;d&HXWBq0n1&DqMk+BON-dFp&SHRdD%jvyN4EwBXR^=+ zHbWvZ$bn(e5!TTR&+e{Ig9cJrA;iF1AV_Fn!o@m1hOu`x_f1r*5(v*Al}4sYh80WT z07&66)vbJxtP81Btq@{_4_Kmv1^QT3l)FSmu3ADeI&6?C0vo_HO5X-t4Q*g!!!^Lp zdHQQMQsF$Au1#XeLI`pI00c658-xW`-tW_N(h4ljfUG`q;Ltky!6MhRL2#*%X`;*R zfMs}iEZLP@wzULfOP9hEtBR^wHa3nU;#BI?QU3`j$c$vl??6G9D>X6y5g5oENHQS- zi1;%~&OV3XWacC7cj#cOCgN0DBJa!50A)upM^(Vfr1t(-{7{qdL$3z}0M4Kr zV1XPXsyPeDQirrR+mm|_b>a`$#fXTLC}V+#WrR9zvYwAY&R_$1kk`|-+aQFlg1jJv zZbC|lKG_Y{dD9@xPM^nBp;r_S5khnH*FQxFN%ToU&k#Z%L1F0Ei!1eQSPO0pS_dKY zfqb1pw>67}b#8cX0^y8#%QyRS23=e%uNTCggisz0(UDJ^?qL?FYnv{FwyDO+H(sVr zP0$)6pWrs3IC~U1LqI-G8VD4uY&yvWI3JU7*>biVC-cRW@lo1nf>g5}@q`vKc+3!j z97Ir!6k~)K>nfWmO%P(N&0C8M~x{CyZ1^c$Jd6xTwT9qMOT}K?L`?CJx-csUz&^KkURl=O<^0^Za*Mm^j%&Kk9y-Dshvi2~)6 zjn;a)Pcn^|IQ`>*t`_U;16&;|=k%Cbt$CZ)A=~lB{h{ZkZuDij2XweJk)NZyV3r@b zc2Q@+HtpgAJ>n*mQE#6bIx?J=J!?t))T8S(Ya1S6gqGgToXOvjBfC7uV(sRDGs9Z7 zz2cBCeL&Are(JKR4f-y!I_tc$?tH6d!Br#bci*>lQ#I@f=(r6gZ_{3WnNwVsu0?ls?tU-?Hg@6A<_XCHqb`n{{S%XZc;PI2&{hmMII zGuzeZYe|WYL$7XnW1p2VH2z>M6>&@`aNq(Ik@T8q2&-cZC`z& z!d2T>nyVM09IuSQM;RA{wy9@9gw18**{r41Q~SHRC22Dj486DT<=!rX{r(Bt*7WM* zwQtilytuID?$Y87ndg>@*IBg5;lA*C(j`P(;3l)V)%$!%VAa@pxtCmJm&Wei*&ulT z@WF4gO-;*6uNL7BG`bqtO)bE3uJ!MIfKWWZfL~n<6yTd zKY!JMN>{7=5&ZqL7at2OyR-FVdDiN-X9_#DoLWCP@|lg9IBwU1to7E1t`2-;6YX>+ zO|zh6aa;;#c-io2DbiORv?V6@SQ{_POByaLczjs3zd%e2o_%8gzcj=l)F`5b|Ac`9 zmyM4sv~L)0YdSKuRa|zHEt`BJJ6(D@ZrPbRDGTi*ruVz=IX|UQYGI^IIrdcSduI8N z8~e_+m313(=#JFk+U7T|lUjLg-Ro0az~L=?*qTsvK4((% zgPrQnUlQxyKC_d+!g<}(rHo5{5y8Gs^Ws}>J6m#k*BZASvyYe}gt-`D8Ags+2HiN1 zMx{`xRz}w&vn|x-&ZYBmh>Jxly;JXE=ElqxqdSd$Yfhn<8X=5>n_^63T6em!HMM&f zZj0H#50hW=#vl*_fl9Ih%*$Y$1lTxfm8Ba&keNf7BG-$|R_ zKlz$iVSHbkv1#D+e(D#Slkz9dqBECz3;IGHkz^Xk58^gPI8$VgLx3HLq!uaYtL|L3cWn&ps53G(c zt$RZY3ZFW8T{KCE~jEhcX1uME#1a;YG&uS zvF*d+Y_`mQHpzaU_4ANJSR=UDm2QvOj<7+Sn!j+Lq{8pd?Xo(h?fYvLW@pY~9K)R{ z6nayvG3ILcjZsJ2>660MINL+%5eu`ahe{pgiM52g)}^~)E*ZaO25Y$3iEf6mFov;l zRJs|3O2ItgWFvYrtO@3p=aT0%+OgKNWVN1!V;m2eIu^^I7#Xu#8dK<$i>XvPm7e~F zp8gU&M@gvu=<|n~tyEQQr>Rm}1W~4}Jn62+E!Ldum*DN*xXYpQ2vO!7?s(q~Avz8D zW4=^pbR=lp$`U50-`%q2A$t;5j^5nT_;-hSX=JY<{&r%v? zt~+M4-=^0+{d0xnb30*vRA;nj&qUAqR~k~!KW)By^nRv8!}-dNtSJu{w7A!-h0>!U zo$8EEGF!&X9gnRT*EITYar3=Z35Bnm?|taey2p)1yJpFkR@Rm)Q&O%dNS2s8ZN$L= z(KB)m?Wb0jojPaU;QjKl@)2HJ3)=@R@S3udVY519S;Ic`%rQIZUBZ$AI=oKF>``XB zY=L!1b}LJxF&2+c({EI(9IpFh73{Zh*4f!T)(xl^UD13W zN;^}0tw+4C?CspXv%Pv%Q=ZB_`c~w89PDzo|I%ptq7%}VS3@q@uIi9wO;g0zr{CT> z?bBFGs}ORy)Qo&HyU{?(s<_2*yx`B#7bRDWjw^@{&`#ecoxzh3eGFTCOj z2syXsh}cpYArs2v1V@PRxddNE@Nj}J7x8f!CQ?XbBB78k5(*`lP%6U}LWzPekn#mm zuADEz6pC>O;otR`#=}3p=P9Kie?m%UIC3Kv`%4!EK#l0raFZZ8bYF$MLYS!7iTOW>>3aj>hBb) zQfZxf;Shg?_aSv}v+EtT+VWF&2a_jIj*r6J6+{F4||s4oq0Famt`;?cbJX zHu3t(nZde#8M)9$99Y&)zakA@k90HXG;6ck1R|pvT#SQrFmi*ah5+N>Y=~(GkM85yORXoG&h~ITLFv|}%bjNN z%V64Y zc=pw;`av(A41Uve{+$!K?u%Ze<=U-&YAq0**?72>_r=jg6_1?X^=^>1O+0i#U&=fw zeP6R(tkqseEgv<|MK{vlVd<~GjBQXxe=oK{HAEa}6wC_30%UB1ff-XM)l^FD2*>xt z@{0&Z>c-x8hitxco1z)P$U5xM>rKVnc#LhhKZQbXg1KQXhTj-kskb-|1;P`IL z0>WPn8_}IGN9>UcOa=~cZ^6R3NV z9&UJEUKu|szsHoDQv=`Le1K9qWhYL(b=z-9g8?m_*5;kGx#Md-@J8t9B`>eq*sNF) z`8>|AGBm`leZ_6ZVR!5Gs#-DrY=@6so!@vcERFQ%TK z)qG&zht$0tp1pe=EO#1`e+xfQ6wUM>e|cL<-qGOByOnM&0tG|5(PG5yLdS17e|B}R z;Au~eMXJp4fKJ;Fv|C_x#Hmf)Q6`xi-@OpJt{Q~e-%Fe5$ITcReCkFWS>$%*9Dk;z zOI2W}EmIQ1k4M~*_6i-bfXC|ZzDGM(+Qcq*3f|oGW!j1T((%!Ul3%5nemL0sHBAw?EM)HK zr%OLlHx3A*1xmUWJDH5{v<`p0Irq$w)yekP)*rIieZ!AYdLyuO+t$s8Y7mndkPxU9j*#?6p( zaM3yOvD^nm*>5A)bhGudTuU{6Qnb0}dGl2hE?>%fIVOI8`LT-N^9zT5N@@)u3Q)#| z5Cte`Lx|$9p8TsPzlZ_<)suhqb7WxM!-AO#Qlh?CP=mBZYWJ`(rp~gb>$4~7pssB? zDx;J>gj(wq5HGVvUAwn|&+N#RQA!!1*20%`9Kf`%xynCQC6&bLtb8BuFRXk+-UNJP zkxUl_Yai_m^95^vL}71jZ7csKSosC6q?ONl-~LcknA*m^koA?nv+C!vldZczw(c78p&fEx#rY?u0q&)*kI@dVEPFu=FuLj^jE*A1r+iUhC(72ME9N z3(8yHtg9}~Uvh47&y^vIvQ3jGA6c~YiPgy&eJD()a62nI}&+7`dnHMC(C*Z~LMPE7&Ce zapyMuH>E9}ynk&|onIisB;U+-7ByzS5k{j>s%x!k(n>>kJlM*3e(4rZN`0*?$adIjYEg+l50_ zul6?Tb!=-~?qKb`S9v=!B|3%5-MoLjtSULWT3 z3zKezy_zI@-)?!yMn#!aaq&#N_rw?On;s;0UNEm$dCT5K?Oh+cH_PyCn;Jf~$*dbA zI^_$VKD(GYz_xVN{W>S&S9P=#dIns*>D#u&Hh$PCaftC-kNXFD2EhxF=TBz-{r(YZYbwLpN=7V;EtN+;^Go@!b=$ zZN?AtxuU6f96s5C#hrl!n0q{VUKq_577i`76+W1^R!l zKz}xsxE!uff)OGvmn#zpWl}buM_@dmoJR;nT&|QW7jhLMKA$a>v-xrI;)VZ&Ib1=u9dKBJCs}?+{Ipcd)yUx4SpnThP&u(~;-v%m1OB#ALuX z!6;xMrLCz-t8F1wfQ4i$(OF1w-&#oD$t<<|!Q*SJBQvm$7+417na(<5ShP$^th;{b zlG?Kp2StG=7T!?XSE+&Zht$X}Rjjfq*WV@uZXz1JC zds~g>K5z1gvF2Q_DH%^*N4w5{bt7b@e{`?xdu8iBB|JE^@{HBKO4GdPLJ!u94mJzh zPwXj*y1p`_Wq8~v#u(2l<>70Lu6ED*u)m?a{qfM-{m$_Gnd}F^72;S z^Jg9n_+aT&RBlx#XG?Iq-S02EHjLX=*>k~?70e-fPA@uS{Q7DWx4z^0Ojr`NY3|nM znWGNu?R)xiP|4&}b530}RoOfl`xM$>&FDoZ*DPsz-1lXSRYb<*-kR2jQfUE4mpbm9 zs?ymd9kBM_+96-M<(q5SC0nOq84V4-e|@Fl$$73ffS8V!?!dT=SbZbA#SqxVo)jVoGxJ<--yg zt2Ofq-QIb|speZ6H5(fDx^K%6(S=OUPXUE@7q5(PELi_y6OR*k&Dm$kpl<8dN>|NJ zdvtaBj+;?v)by*SIRi@GZo)=5`>hV&+QC!s-u-mF#(NcE1?#47&>xJ(f?~WOtWS4v&=6|rwzLT@!m1`6KqAP7=%kv@v zd;{1f5I3+0MY`$AUn3T`wNF)S@;1L{*oX@|fpkO|Sm(HCnF$G&H;0t&- zE@ca35-vGc|6pdTu>9B4Z_Q$)JG=(@!|C@y?djM2x29i9AMX%%T-gC6HQRaz}e)~I@58t<@?YT#uUE7R1 zyOUwUMd%_8Q~11nkzHqF_ru|i1>IsV(&J{_98X=j<;u~7(AIMrstWctzigbjJ6e9L z6{T$azEuk|nI4P1|FJfoAuDce#+|juRLWWER@t)q>sgnkFwHZqA}YcX2S#)o zS-AFU9lz9p57vyFwl4nw>!``Zhbx>inzkO-chr$7KG*(9bZI+qOKBZK-1Kpsdvo3E z&q-$eQ`va+xU&`;of;_KRh(Uuyx%b|u!pjnty|O^|o|f*+bHGo$(rJ z*TJVY+*#w0nj4guH-&|5N}r2&8L>#RVY|9c*~z57*?mWLzVfcyW(${L;$w>WCT+2l zwTa!=uTXY-3zLe&QjiOl6%xMY3sO42cx(y(JiJOnR#2X zsQIy_<#+dc-QS}rSn{mp?cv%F#lz8cS9#@}bT{M9gP%8U`g%^`D(&Es@WS|+$Dhe} z8E5xxQslAx33nK~CG(b+Db;E!cRd{``>^Y1(T7Gs*-gX8*%o{l_8};YZ?l~3?l$|_ zmaE;TG|K7EzU$a4!y_;7j^p|FBcGhLUG8>b*~O)Gf+kGJ>YJp&ndfel90>_lQs2#~ zOgTFj@HC96xi&3bx|Vf{F@z4gc5yPI4rp66`Vw}tnjA)$Sw@oiUU26et1{wXd) za-!kOCV9bW9RqVVc;Rka%el8VJq=q^r|rt8Lv|;1n~R3dIo+Vg*@!-N%65~Myq*}o zee3SbHM5_KGFG489=Ol!A5Qte(0glJr>wuw;=rns2NJvO&HMCNt9j7I#OH;Ll_ZmY z&}1X(&;@Cy6%XIItYEl9i-4Cddvi;dj5(j2)@^-TkJAH;W}Of78+@zZ8&>AXt2^tr z4{RFW#pHPIHHcu9&xN_Sz zf2YQ-_{z)Z4F#_j97iKZ+|G`h5pr!|l;0A^jEl*p1;+)C8igeXmc~xFnEuJ9RrNbJ zE_+Pm(*~{<>GM}y=Lg@u?)rM~lD7Odp~Ls&e2kDcUJy6*%9em}DH+i{=M5+--4XQ$ zBg}6*37?x;L=J6Ll)8P7rF(jW-{lT3=UKG8y}tjYTTb#5#*quV5pP1%3+;N3skhI? z=iL4{ap2~S5I(I34nkclgHow?5Qayd@;laB68e?>_*=&PuN;I1hOjEl>>JhjOV8ki zv(d^lR}0 znrr3fjXi~>$2YAgob}O$Xwt3ujXrm{{fh$A*dqzkZe7~deY7R*Fg>e9&x922{p=h4 zUP!Gt*W&^K(Sqt@38XC2wuayr$R`Y7?<^R^?UXP&Rwe{Axoz3+U-cn4pODbK6B zF(GW@up?)-CHQS9vMQN4{ngM}bN7x|(uN$r&D=y`clhv&Xt zk%L)HCH_x`=sbf^EaXc^fWEGlBT&3IbxF6Y1KsBz&bc_J*QG%XvIdC02vB}+BK~Tm zN&6>cxXBJ|{b;-XjVC&5#8(`0leT*`6S{Sb+qZqyhssa)J5(-Rw~?A_ymw5yp{D&G z9UOIHcTSs@FHBpHkUc)F-jUEdwphKOXT{o9t8E6zwmDCErv4D!Kax2CmuNcpj_)>g z^MeLQ*b5FtSel;e>iN2A`h&>JL&Ob&9vg-9o6#-%*r-6;vSkar>|B``7mUYy1ASegC)HzGPa5 zKq69LJONuS74W5eKF*WMF}8#&RZSad-SX z86C&zSO)ztmO)#m&*(6Fz00^|59+JITSHp89)G6zYWDq)r&IXr-blwWjy`o;m(hW7 z*djyjcJJRxD&b(bE_0-Xfi{L!UVpYzc$YAz&@gW&9f6#HLQX#3_%HpU<8LjcU6<{U zsUA-b?NJ=pbjV<<9^;m`&}q4!N$n|ccS3|rrA+Mt{|1HGsB z;Wc}Ng+r`jdOoaqu!;MRYidB!Kd{DRnN$EBei5~seK^S*!o_3I>e8a3LM#+-G(&HIsQ z{>p_qzbJ!}fn`vJ{~~Eyn>nILai~mCdTLj5!Ae@g-H%V$ec>MkyM#O0=iI#&f7jyu z`)yW_jqS2UU;10$&xfr2PJEIfr<+2d55%G|H^Xm?GTL6B!Qdk65e?+{1~^$GDiO zF>}D^PL$D~VyP6&#MlU4mZ#KuYu@nwJhi4p`${lLPjd3}gk#NSDrXMWekyw3WJp-S z>J!AL?YYLe<1R(`jCmZ?rAOrIy~Uf1oIHA;sqXwbuf^qcIjfI&bZ&iV`5RSM^N(0N zw^2LxZy7Spq}AFnF-e@qsC(%8-t%v7JN>fko<-I5cL%mvs?(YD$Wt@td$1EHoto3@ zY)^c+fResm5!c+IP{E8l6F>RYw)dVCo8rDbKzKCcV z`G}|g`QHIT5@u;^LgGxN7#p=rrz01d6w$9Qzp`W8R?`orY0hV#?cS|<$?4~?ll!3b z;M|?3bKX2Ve%f@qq)#`$;q%=WJeedjvwLKc@cPs!kM<*T@3-@gYrXp15}V%qlzB9t zCzjT+>e4k?%NNFM@;MoG&9$2L&*Jj7zmpB5f0>c|_R@xuPD?5m7GGY&_dZ@%rj$0{ z8F;YvXwjk(Mo@9IdgqJSc2=FwxQq6)m@_r6viK9Sn(nxpH8CV}xvX+NyHqjF;`#AH zX7=^ig7-0Lc~nfK=(A5gaqIk$Yxx%f7Ck<6?My(L9cAm`(b>ThvRdZPSuw8o4BGWB zynN1`K0`M&wFBD+Sk_?s02>=@pT7*IuJQiJSE&6te;MrGGT7%Shl5Mxd_GsG5aJjY z=Lls2j!?l75fUzkjo};)N5mmG5?m;gVQjXDPbfqJ8CxO~5emM5gUfYkD&Lcwnlu$B zjK|~g_)?jI&4b(WI6N6g!o?JFo=XUC5_NeQ&`xv4o7r|HDKhWwbD zdW0W|9DK;y3SoMpAU&xcV}i#ujl!lwoe)?wb2Zl zQ#8dV|K+6Pl*d~xD|^Z;{;|%HJh9H-*piB)8%49s-kDIZc6diWS*lza!}f@`@oA7{ zVlwBz-p1}vPktPdvLImkVPchh&12Txl&qh{D*lS*U(qy#C~4IHfgtDq+oJi|(&39l zgq+Wl%Ht} zNay-{>YH?~zo)kK&NZ9Os@#l`uuG5d&Sn(;`6hYY;IgJHwF!uI-t6%bAbKZsL2Hq zNZ&s|&!8U&C(tSeH&OL30X3RUGnR?E)v$5HPkTcni%-wbi?>Zm-H1dw+&XG%5 z2cnw2(b(9u@k`o2#%8QDH)ySeui3JIh1+-J78i0xHqZR+w}NWN0lpU}`-;8D6`BE2 z&8DmBbdo*9uRn;gzc6-~SMm7HX%)LmTH2MZi_|2yU|WmQqdJUoec>C$dz7{3UG_SO z8F$GVr!J!omb~NLOuACGtiz5&9T}t3_*%D!tFh)by?MJ{1YFD2wwOB>%iH#)w0FeZmRtxi>#-}_ecs>i!* z3%tVgT~fMa>zrQK8w?9wFsZjsR{E0pO)jWbUpGG}81|SpwZWa_$fPG;6A$$3(Pz;W zMf?Vy;0}B9&!QB6<@MW_k^jo;UwQqXl-JLukW9*v$)r*NALHNzkHBz_P$87dIU)(0 zqY%jnu0WxXad-rmBg1hnS4K$K0y&p2;Yp;pOv=-Jc=3B`vR2TC!;vU(f-e!^xI`qu zq*At!&z0i196szw@P7PWu|E{Q{r&ff8yo3@K88X!#_$owuuy*%S>Fb}vDn-9*9!$G zb4xV&Zm~;`Ni_=vZ^4ks`bW1=FyPBKn|>U`F(DTQdi&PcF4rko2IUHtK^dU4UFxDG z)R;w2V~0AOrw{K>ESol>w%3Yze3=qsj+sL43(J}gSmBmrEPzh4CLiO}+m{Tr@Guef z`SXZe_*wIL#D9CgAH+|*tf~uct}Y%pXkGLNMnl)+XA7wGql%8NCkH3@o~ESU%BeQ_z-n z9-X37$MbeRY5So*8Lj{FRbAt6-{mFCDv;6o#fO_jOj_9GG*9+%uIpj(njSB^_NYxq zS`@-+Wo`a&%W+XUG>VY`^$(A6?e{}CBd_x6i7 zP3pg8D;2BX|L&rpnPt1Lz1z=Qv@~c#|3?{5ieG2U-bcOLeaj?_f0Q!lakHXh@y<)9 zH*NL2iu@`Zu#F*D53FPe*8d&)|Eq`ovqmLwu0kP`$azu>WAg+Y9K-lBiG<6M;A~vN zX3K?yNPuAqu0kr3DTF+>0%J=Am{20&$$5M}pL8z2$I_oQs)UQN`BDj+Q1E2}85@&x zF|L5%5qzG6FX9L>(5MEb0A3=gFZ3T@V4@&4LWpSswFWhsXm^E5oh(tymGL!&D4#%y zGla2o5# z->5NHFO`jU8`k|`_@YZ~P?hT8U9)ZPBAWUx;_c~j)3H}>`#GUm8;hkgwijOQ<8$g| z|C5|%n+rzV>_73y{1x%@v`;^@iWz(`dROApnJK=Lu~fuw)^$j$u#H1kl$%^&y7SV; z923TQT`cw8G(c4v(SG=?xljd7aBy%;(&857&m^nE3U`c7n>5R~*~Uc{d-en_e5tit z*mlwO$C=qPDU_M^-8;K2d(n$%|9h{w}sjo+BmQDbM% zGL0*D(zIx|Bxz)@$BzET$4+*4J9+#0sICp=?~h9?85;b-ijd_a`aSPj-EPsKu|Wq* zit28Nm|z!lVR@^#3xO1y`k7L1-lsY{k6mxK?s>>K`_Z#j*6S85-^BhjDeGg|3%{59 zFZ4fHsop`EZdtS^_GZ`}W!yBI2QN3>+V=j#hvsBCkN4DDarJhGWW=c7_!J)M>AAoA zqg_)KdEBk?QPUTP-+A19Nwdk94=+tDijO2DootTGy|Qe1tUuZvrgmK0T>40RidK?2 zF=w(@oAhH=t(+=1T3<8yr+w<1A3!*$CzH}|D6?Rq@e5u)fd&?Cxzfpp8!BcWavL7Qe5J$meRyWY?v zcMgv@w8HV=sXcXXzIgk|y3_trx#$D0W1rne*81J&u0+G0xp5<2(M+qLT<3`R4VyRn zuh5R(;lm5&iz^#C*mig|)x6kE{VCbUx4;LrZn4U4ZN2BdS4R7uku|3-?tj+d9~S#) z|Dlc(KCK$Jq3ZrUNxwOBc8eW*FcVsiuo`3?Hwlj6+X9mhR(y|eYs+@_Rad0l&_ zE4Ljz!@88Y*ZTH!>f0NxYxicJ9)94lSs#F*1^Yy+wPTvT>li(`e0b-mj8#|DlCvuP zU-mrRsLw9vLmP5qb2FB8X_A$Fk2yT+kkOSReY_3~$7yc;8|5EQ5w^%(xq#ZCB*N95 zwl&xG9edcvihhH=cW+IXUNl`-=vzmX^ysX^-kU}Vg-)!{_;ZaWrDdE+*}lXVtw>wg zeXHAc-}(Rp{k>h&b8j}S9%R|W^>N0BgAWp#^jq@i_^J)7sx5GF#%$Mx{=?ViXT6Zr zuXvm4yY$(y%P;PG6lOJRwRx|)^6SgB~nan&q%Vzc4?yHB> zw{zT^hpBF^x-iVX)x$l*(^4(Hd`@07zIftzz>&rGa-%oD>Fmbt2DM5xaZ*Dm)t)*% zNFIBlAhr>y2%!cesoFq|BJu;>OezZ@rXK?#XQQY@LIWjvolW{^;}R5_el(~AOx9E- zYammh7HQ9}p@IIPUAu=sp+~huu1wUxL!pkVjsBr|IbRx#kb5vn4SSu7Aj$x1a5 zOK3C+YL!A6OBmpNrSA$yC>m``!dqQkT@8vCC=6A9%~2Jlv935Q6j;^0&(DB@$fQ08 zoS0CJm5IpWs!;ZxEQk!{hoPP(4Qe=&C1t7h`mYu?fNKnek!w}^rMkgCp!O)u6$<6L zz|I+VP~w+C5+z(2Qy0$Eft@+*fOzm>LT3b(lvyH-%frdVV)~aqfs!V2LLo_v)si(` zp(3UxJ}#lA0PuP}LEyL^1+ncB%BPYwkjZ+^Pz)Iwsn#T+sAwn4fvkbaLP2axD0l4W z$O6(e(6zgfwTxkw)0Hp&TrisTRoz@b&q;`37)K(MVO;o1Jzpwd^A%h<9~W>0Ts}_# z1)iO$!Cgp(Xzv{drJ{qo0FK59iPBi542pvSI_@%6TwG$jQmZ6LE`cppj~N_eQ4qTU z3AYsrVndl+mZKvKBk&73+`whPt}IjqWBkSc$r{f!by9)kE- zc^GU0Lseq13=Hi~WLsCj+5}aRPo=|c$#U9I)|df>SgCG5x`qnZkcDGO$dk1RGDVGb zlA^~Pjww2P^C-v$8NPN=`x{awWVvBugl3T4ctc7Wrq60q&NWo zKL7w901w)H@4ir~RjO9Xqlg5RT3b^Jd8r;WAWXi#4TLeYLA@B-AkzA(uxJ?-p{2SC z%rG1j7 zvWPd#5wL+!-PcP1RF^jhEjS(C`fF-Sz<49L4-_u0&VnNM)md~>a*Xu_l}A$$Qr4(u z3PKFntiL&9gQ~MAs2>$d3s+NOs3cSrCPI{d5TbzkgR&Y<2qqT<(-B2ZMW`71qdJ+e2RvW0#c0`h5#;=8Uwm1ot>iR5RVl=3;W-+T)l9hy3GV-zt)S z%fI>&Vb%!y7gYTf7n9hL$Tk4gW6(7<^Dw1`F^zx7jyh@mZD#zAFtb6;gHV`(eWOZB zi1*YG>LfyK@Gqo#jSfdC3Syr{2pvWUJx7Rg6d}enBZQ8F>N)|tlX_)#8X>0F88~we z%)0ZiJAx2nB^@EC?QRB7a@RcxKLuKyjJM4itB6A{b@u)(nr3Sv`9 zR{*9RU{2Cv1t4h(ZNleU$YPa5JUDs3<*~t}2X7&I$|R9WjV6((@lOl}ARK}C5Ids) z-sI(4A}%3TqOEc7zI!#;isaQA8IchA88Fzs+X4IlJv4@K{qA+Z1F>vv!dEB0hAP)`C}rx0Q~0%K6l!cX7{bQyLf zu)D6~oa$2eQ3ks!Fi)KUbNsV6D8jgW4iDq9ML=M+DiN5(Q=yF2>NxgyoN1tdp{H8U z6~EK3_7f9gl^X4DyYE2jctYzbk;~N@gBRtcCn`7yhBlZ?UMPqSYzVrZ<>**V`X^x2 zGYqa2sV1qqe?xcD zMh_(fKn!g_CsTiZ8U@Y=u{}t$%n}8$qx3!%4O|FTB@LkuG=x6V5c)(zsEUSAHK0t_ z`72a9LNq!;bUH#tbe#Y`qaol}=Ksgum%z7C9skctKD3UV`vwv@29iMR*pBTuAso4# z5IYG;2uJ$^Sz6m7vLqxqPAD|tzDgk!3ZaAog@*fVX`u&{8~Sg7QjT7fUbN*1DTP7{ z*#FP>?c3FR>(y$d*a?K_ldQ(OtC@GqyqPy|-aIdJHDf?jFkzhluS5wdQjCf`atn+` zp#lS1i~^ft`1E2F%EdU>Y>gqh`-r#ugb6DP*f;|yk7iM%W>IX)qhcIqsvYw`#&O|z zsxlf#ox{!cuc76MwHsZ@VSH`k@RvPA5e}d1A=<{_pogfN!x&!A;&9kQbUKG)9-_q@ zKGj2XEQdwWdTtWY*SyWOAvTr-*|n8j_otrgiGDbU=)plm4-F#v(IBE94(p`2bI!q}p`M5Me-q`X3eVFtqq{gw!$4PgL#o`_x}!dL^_ znYJjTyiP=aB7#-TCftV*(O-$^YK3U4LUfHn^eu(xT7?aCP<-@lh2V^!=ZlGMRES(!`5_xLDNHcJ$!=)aV2FT$| zBDJs)&@5aIBk~QMOmsMry6FhKbtKL(S*g%bL~1P?u;vn}qvjDYU*dd-H723pv;{!1 z5c**;e%ge~5?q$zax{_edxe-*_Nc|nn4lB2;K_1aR^YOd-(HPB*5Gm+R;dbzzKlOk zCQ^IDfSyrErDqjVdr!rm30%5y*?=-^1aulMU%};cT+YykmfnAONu^D=^G`r;;_@CY zZ+S8H5S;@I=i&u+63Yc>3JBsxSc6_TVv4X(raNNbJyeFH5vQP84kc1U%L+)v36RXw z+l)V23dlE%$TJlh@O&aO%!KS4a`%5wiC~g%qnyLLM;=SY^_X$0rn7CNVx>oZvF4h%(98 zqgL1U-<+X;Kb@Oc`c7U=Oft{$Qd%-SwvwrO2S_Yct4!u0iN5CJd|pEs*&p`u2=l}$ zkIetf9HYZB$>V4yk5*AsF)XT>dAJb9<1zO*ddY%S8Kn}2+OXpT(U7*GYC+2?|Dr%= zII@w+YABhC22z{6n9@QWrq!fXB(o^WeZnXx$o>>Y#t8!{G!uWp*iapiBLii){-1r@$_S-h*xWbFTkjf7;omu=QZK zT5VH7|LuxBsu=bt*MEI%Qah1@9SZ#i8x;D_(0NYws4*0CiGxYX=ES+FzrI!}Ge7Mm z4%3(ck~n6V4wOwQnxh%j-$u9QsAPt+LGJ`C-nYb#4JE_TfM}E2nxnEMTC{dCW}(o0 zp0$ewvvixO>SVh!NOT$DdOf>tX4k9P^%i!$2hK>?+PaDq)S-fTqbQdHXqRHn$mWY& zE|vb0OFm~*a-1*1J~iiyuuCy#wA!Y2^F`RIqHUUCo~Q`(L=|eVpC*Yu_!{iR5uS$u z62~0php;s3-@?V+OcC?KjDpDQ(2RO-OnP3(1ko4g5B+Ht_>1IEyzL` zf-IyW$h-xnXzF4r*r&SXx=%R!ICBPCI7KH;zX~Tr&{jBA<+CA~?&Oip6kTaa=SiX< zoL0GH!fFvt-4&CA*qvqSL|uq<%?NKF{`b*$%ul+T^d0lV2zF?{={t*_bK{3G^&E6u zE`Au7b|`!>4*HHQoY(7t3oqv98uh`GZYx+m_|-q_vIRrD-1NoZk2k&K1CK(;@SRBm zvM4`i4Jgd~3{y1iBeh7_$N&qYtYRztRf#U7Z%t-WcBRp-p!sG7#do?i1N6Yv%>Fxh zL-#TX%(gNiDYMV71VYa2B@ioEpGyf;SHMPHF;KE68i<1UFguc2l=94vc{}|U0rfA6 zCH(WXM5;BG@;9wsy+RP^#op#xQSTw~9scWj&wiC~pX|9`g~+7+gp~(V>oH$jKhE;t zTCtZlXu{nfZTYM?*l9U+C1h-6|HznOL^3_cTrGk)V0!0`#yc~qGf@Ub(LB~PB6ago zR$-riBN7fqEVl2WL$i+>vs=uAacN!5vlAo3k!e}TGsVeRJLoT`2~?D=IH{i9AWIon z)c@htO~ZfkZ_K-Nos@O0omrCuAXV_2Aglq>BuZDVQf1wm1-F$LX_E+acVO!f5j})G zAbiu<9UR71rQ11-1^l}>j5w=%IgB_fYz@H&aaP7}5uJ5EzYmgka~Q#Fw{aLjgtu}S z!D_~R>>j&^-$&@6ffL(J9^m(f3;0JMG+r+P+mU9J69JOO`-oz@kN*~%%#3%iUFFC8 zK2|~=}Zl03rj z+#-qyo?Da)Q9)Q$L1-gZQ4ro}7pZ^ET5*kP&eJ4=y~qSZRURw*S<)Y9G;~9+bzR zBL(ps3yxolizRr+Ia-Ge8Z07b7e$^bU`)%%8S*4Lf%?ajv<3k%4oSOq}bMW5KOH>M`Tkux-eW zb0G=4iF*s|Rc2v7bMOCwk59rSz2N79k2A5b8P%D2(V!^J!kCQ}#@1COy1=12WZ}LO z#pOK4%))Grg_()wtJ}tE8)8c;S(>=hQB4b$t8W|^o zeaphpWGc{}2y|8jW1V1Qb%}AuhLzI~@A8Na1Y(?0!$w3=#G~*<)4y^Znj*Wm_8CWwJ0=sE&Ew<-Y-`>Qn(D22pyThrJW;H!AoEncX z*s7`SaA!OCIxE9|cOSz_yD)YW!}{zQR{a7otZvnAaK)vc=egDAcvw~KxwPbq#-)Q& z`mpPYSMT39qV93gmFjBMT(Ruk`&f2Q zuuvkkbx*KssXe=vebLxeZEufvq+D_8t@}82 zPjG6PJ*N)-qH(H^839$TT2?o}z9DswFzR4?Mji4+V^nox%B{odo_#~=o)}Vx*mLU8 zFB+!~(QVcB;gA+{WdiJTUF{Km9cs_7!@g+zI;cIF3Z%k8SG@YbzOi*rjIG1$d3E>~ zjaNtMV{2DZO9W%llooY2$=c^|-6LE(+@5Pke9^dec(fxB?2OOI#o^jUMy%kq3MoeB z48*IlP)XzxD?+lh5lGlQQi|=e@%yR?-PN1uVvE1#Utgfm88gBwQy{`_j7S`5FBqft zCc&`b!lKUfVgvY)|LqipC^0sSkG_$!du5>4XNg-!*>mgIy_{Q1!of(aD`c9*;8@|F zYp%V|G@12HSlFIrcJ_ptmScfHBK)@QacqH>~NZMkE-BwJe)zQA`4y(PU|bjDU{_%W>@YDM^joNs-;i> z6gJQmNg;zB2#4dT2Hue)d7`~b`7x8o6?Z!?3~t@Q;Q}Js!C@reE9WQCBLUxA{66Y+ z7l)C6?`{qw0pH^sMgl$@C4vvS2WKGTgNC@1!$`pQ6o4Ju^h1}CCAHh#Ae3i zcu1m$1bIlJCmgZK(#QXqi2lNlF)~ugiwX0rM{ME z`}C*EVHXztPh zni$DE>0>f?^@PlHn!V#7f|gu+7Lz@RS5mli;j$hV%ek4-X_+h;->zoti`VX?_jKt{vr%TvLP%g3j;;?x z!l66*t*98EP+S!C3SLxpv^qNyb+%d5g6u^dZ5EYx!jk#TE7mvc=(n=!Ig+nAi>T); zcG^wW!>5oZ*jhszGK>ykwJg9%Tf@v+7G|&I1ZyqVELh8dTl3p zi2ZkS)Rs}(8x>NZ_r!ihtue-xunL>?FEp!Ol)dWJ)~YXPn!jRwL*@KPSc|6o@r2eE z-rx^mq8>&zd=DIa!so4iWrqTKUm^DYiebe5=h9Ht1~QwaNM?)T>}@l`+BQp$ zUU*l(Rn^MFW3bY`mz^vthJ!wcv1`c=QiCv@TK*kw6$hw)$FAmXJ6Wdt5!VT zZ^gw4+y*C@4Xc{EP%+C}lD)ir6j2}&@uxZhDSu}m73|QGyt(7CNI1Ch*?z0TuZq)k zcxVvUI8Zhvtn|i-WKcSTve%-hPM~ptOdvDwqWy=BD5ojLZJB*)yuxVJPjz zW@(4JDQzEXplQj9clu3QVHpmP;WHeSP20mG@~Z5TqZi)OZYYHg)L>YOUz zoQ}7v6;emmDCGNxm!1D?`i^hRvtXWqD%emh)xkX6U}<=_^DUtlB`g?#rW@KFPG}J= znKVjxbDnKjfD(EKpoAlm8>7LFL@XNXG7EV_o`ozNsAe3}5lbcGF|(hyyDy+3h=>oO zi82-rKtm3X2T!f+ibrCBkkQ$mD4gJos1GZ2Yj)y-TGOa!{|H#8Df%kaUs^|Y?u-d=NI6$`@AK+5gUjCJI2 zJXP5lh_**Gs9UJgv-t8OROwY5#?s=&9LCb(H#m%?#qV(#%ZVp)7|V&*ahRRe#bGQ1 zZsM@G#CM<{bTh{;3rl?LbZDC;J_YA=;e4)qm-v3im-w*MCoJ)?Q(CM`d{_p|w8V$= zw{Z5Bu*ApQ%->N+xk(|qSt0taV!E8I`%KK>r8^a(yDW#UW43;uqMzo1;3mX9W553o zg(!WTQ;a1(Ed62m&^SK}OMEzUOI+fE$$}+8ECFI!5=($s_QP3QSn`8I`d?l$Pjsv$ zb`l=k<2XjLw~qgfW25nRe#b`l=LtqFSgu%(ixkke8h6&$e=dlwL?n-D1A;^dDBr3+)sskj6 z8O~_RCv0nPmqd&3K&aAZHo={q{);W@=ek%A$8SMPZ0+KUcb{Su#gX=jV^+ne7$@LD z`}Mb0%y0lzKIf(Fow8_*h3uHXycMHyY!C$4fGx6ZisCmUQB3PbU0>><#(S}bwA!kU z;b?-bx?45mK#F9BQ?~NS__lY7BojqLF7p>jevAhbN&C}2Op*MaB$7trp>TJ1Vab5h8^4ly=O;Naa&Sw#aK3sn&>4W4ef`qV-I8Ob^BBqSI6n zi^*7lH6lj&)KO_JAQb_P1EC=^oFSIa=}ftbV|qVsI==KXHE%S8FnxwDq{+<8;a)a} z9=oFDq?Xu8ivr2iYD9%HLl!1&@v$pfDg%)SjNOsPE?BiB8t}Kp68^c7h(6KGq()EN zHJN2cvghFH$wg)r!PTQ6nwz_Nl&ck@tqMue+!HZU zSr*G;$SUKNe#}FX|A|yuA@(8ksKv_&OJ?LwK0WNLbruAkmQQD?e9KF|P$9`N-(P{3 z#t8g&!#P8rS&$>$95+{BSBMWl7$F50Ns*EC#gdz$E^ z1>g2kUqcfjSk)Xztn)(-gRy8-3u3cG(w~a?wGF{YS4h*ts!iL}BEP_yp9rnkXfuBb8~cdea&tIK@%K+th~`jp?Fg2`8a5olE{dQAR9s5fY^1k$xW4JTNAPpYxw;!gw6YU*CFY{85|x*L=SKnkvms#7%r6yISd!il^mWRL?cZk zq9^!$xM|PhaJhhg5)p;@{ey%$PA0+@aQ2x(M3?b*4ke=hhYUZ#Qr8NC`wBasA zDdjT1CLuP$mAm@uJ(Y=z2qg%ND$lFao@V32{hEXT$4GLy{)gcUF}CYl?x z_$K;rRN68sy2TJ&sILj7Lz@Q3EwH2JO46zjsyO>B7AcVIJf zK5fA>No|It;_wYb`PRU~ChD7ZgpCB3I7lGE3toj7hEtHs{z@AX_klH5|Qbd=NU8o4MQ6MXm zsN8T72_{%Js!%fj_3nWu4GtVvx;|&hNXvdTg zP%tKh6wEo$vG!orJgwMV1m7`!$?A{J$BGpPfLv6f;os^nAyn;sTKOa?&rJwN^8V4>BJ zh0ZjLSvQ6q3|<~|C>eK`Df(Ki5qt<8Y3y6eWE2|)V4lXYYaN-VajY1|v0)fn3{@qQ zp$czLf9py62#Vbj-`oF|st;ng*-=S)v(F%H#L!4s$@JtdN}^TGTGApRCm2hdwRUa` zOQyA8)#{eHtF_Q6pK%M8CxjJ42x(VB2s8L$vrS#iRQJXdb)a^N8qzxuQkmhL^@+Q| zo3k53DAL{>B~u__CZ{V?j%m#W?KaYCt|G&z#VB>>y+O=UCf6wvcY1Qp{`y&%VTuWx zbBuJ#Wrmrvd=B((?*7)88KNad?grWH&q<}~VK%GXmTjzx=y`~9^0^u_N~R>4fU-G5 zT1st}HEJQbdW0_`EcC^Zw99p$yy`B@eey~w<(X<>q`fC-)aOlJ3-%g$UE`o%1x=~^ zXb{=uJsEIc>@H|ZEG+cVmWCyZ94I+1#PqRdowTL67z5v{=!-QLKAiHN^tYxQWiNS? zKW~z^%gIgj8D-j`V@MBtW?=)HTTIvK?$nL_ zEsW#rg>n2oVPxB5`wC-PcR{%wU{P+#WQRWyiu=36(bm`o=2nHnrg-%+YgVmZxFA<+ z)lTxSu#s91JwAfi|9w(=uR?ty06y<3bG*Hj?!UK7X%-7Mv&xjEbc{tx1Id(@2q&$< za_-!yb~1UP6cXUUK0Nk6L;A1X?Xu|)&52aCeKvtu+%#@9=N>a-4R1m}TC)4ui)Hz4 z5X;@T{^&Df0WylCO~4$}oXmX9d*(QW2h_E!Uf~b2^YN0%YZ8eC0}+29p#}U=Jq1Hr z+OM=#j)pj9RgOv?ajbj7ghkG1H;IIt_Gj-gK{WiQ)=Ve6mQi7Uds*CXH^?HKJe#j7 z>R*{0a3@b%XzaW+Evxej3b50T>GaVMzykW}NMiptjU@IzL^y>sM07p7Zf4i3+4UB7 zy~oJjhf|xVzvrM*Ae|9FX9Uj;VA6LfV zvAjVs4cuKmi@_Rxj>+feT`VWsi{*sfpj|&_VyVZ7L#0l)M%txf+;)w`V)52MaGie& zvSQAkyCT^zuXAt|ZPdMFe4H>}glb63HXn0EHp*2!{vX*_iAQi(322?Xa4 zbNU$aXj-ail{l1pbk>Fw+TyN2Lf;LE6_OI<)mx<{)@zAe7fHgB^VOIt?s1{(kMqF> zLPTxj!^+$xLCbWa!a(_Clxr2T%g*jb&~o<0WZL++tF|Vxh1jH#?spA$kiEd|-h`L^ zmYHK01Wr%NVdym`aLn>#8ZK>Yx?4YlooPrEritZdj#_p`LNpddj#)9QErRO$9JY`& zkNrkAIIsiG)hXeJZ6LdR3DOr%E~FlHik0S+Md3(FOZboJifEXY>g%J6=J^AmP(n*4 z{mYiDTJ4|hpDJbPysZD_pE8`NGEnkQ8RXy1>ZV)yH&0X*y zS06tkJ{{}yGM}9y{i*dt=~C>H3GAxXYgoJkF}0j#FI5NaR;k*>jF7uv-#W??Y{y+* zYqTb8AA?lWNa@WFw8!UC5Bp-@mwK9OzeJ>jh!l;8+K3e7cppxrj382wRT|l(k$-M1 z>1Vtr_!;FBh?I#)_Dw_w6Dd=PltYM=N}epTj)-Ov(QG0*jF8uz=y0C*{YWA@ib$Eu zbH6VpQkD|Y(L_{@M4L54>IAHD4|D#fj9Tz!Vdbd|Qw2eTAj8XWs?D z@$%V7Db9Xg#J`LAw~v3T{2M9iL1qw`M&vvBO`^fTw?aX}PW3pPQ-u`W zDl+@26Q03kKg=oiC-RLQOLPF<_7gHts>eNt7oW!+B99-<^emA&=jXWNVX2r|ZOi#@ zkiQ9DLY0moLa(yVN&#LdzzYO;KGD#BA3uDqLPYb3hTb;(UjQ-lGVv@E;3WdwB*0UM zhMx80N|xP!GSSdqZAJQWq639@Dg+o$!L1=}eI%SrRd#Bfty%(U%fYh;v)`gVgkQ1G z5_Z427I7UV)WcHAdyMT_zM(`O%>BG;=eAT>-cs=vV(u7=;VqVDos$m-wd5m6l#k4x zIMINY;rARycJeu_O^6+Ma4?5);6W9Kk&e}XA&160=)ObvJE%*$j-I7_FX#6c@Fe~C zp!quaI~$Saox`Ugg*%5&M@n{Hwlj$6We(pn0p)M5?I1M;HKCG^Bc4OP@`oQdl>e+#s+0|{T?Oh)!Q`!oeYwz*V1&ypE zI6?qbz&H8~-)Jj*qu%&No$-wn_xMJ7dwe6oKEBKN_h9~wT>Q8X*2A~)AKU^MY4Gul z!3y6Pu<(sR3*ShAk8ki1z7c$gZzKuBH!|Mh8(DAheE|PP%6t5c#9{a@Q|WpS6;ZGw z5RO*!@0wB-vjKci??JZjlt}MP@X;*_6;pF9TZH?l*g$~KXcbG!V|+wAib;95n3Ruw zq!g+|9v{*7eEL4NVvIUIG?hX_Rebj-s*jXMe1tNm&o7smTYE!odUYI1-4?f_ga$B({&%N4j>iAy6M%=YO=G#rK> z&GC`yIUKi-z-2BjSNq5}q?c%`k94@@+09x(GxdTY<^pVfM zlWnR}y?5jGy}10+N2>B1pyz$07QdjEn11CWwf9Bb{G@{u~>Z9qG4c^8*AaQQnfJ8}6JF7M&;Z(QET`tdi93tY5sV}M*K0&AE@WwwfeWF#S^hkz@ttkMNuHr!*#$N$|m)RkbUQ>3A8;0L%t7~oQSY=Bc-4RF4F z0~`i8^?&B*rnng0hW791R#Tm2bQ_A%%~QX4j*>RjycpXQW~xmpf~n^Fq_?-%wARYl znN>CZO8=UumKsV*xwqP1&xX62#@TJ5*)!{AH)yl#8)w(lvEi=IT^}h^f7D!CT7Ywu z3Y8JEDkm zYhg4Vk1Zgza7+QI%D4hu@nbee`{6cJV^0OK%+j6-c>4n{sUD_w#(tWL9ygL{g#Y|> z+qtVgK%12yFQwiD2McXi;M{inyf5Bpb+(OGZ`)|~pT|ZU#Tt#Z->52~l?vUo(hS~8 zGi+O_!M2qeK98+5I^9a6!CKyB3tPn2Dst0Wb-cB7yTdASGi_UI=I61s#-v+o3~Q~H zHSa@H0C&JwiI_td?hXKOYT;Bo zoRc@iN2HDn5viVboT5Gy^Mnz&w+=2Q_|BNm3^Ao}lPL+j3SXHg1;1Jsk?%5%Xg!hd z+8|Lkk?+^lL>su{Ya@}bzLaYKoSf;w$(afwRC{}Sd)shu4VzL78j75Ytfln7+bOLL zRkTz&TB`IYxC#`ZrF@avRJ<}AtwB2-++6#Np6b`~!J2&`4Jt2O9|*;g;MpQQ5UyP4 zkP?uYy`G8ITfv}Cd>(e+QX z;Gc=gN6xCQtFNh>Q9q-8R&`y&jQZ-j+F36XmHXmaa$O)%U;hdct+S?h9chRxh|oN~ zRUEM*G|&Qv22xo+EQ~E#ffl+iOAE2YcIcEoEkq72gqC70^eU0>p8B8PF1FMJo0ckR zuJ!l!uvg92!SbqIOQ6;xj9U9^{mtQZiP)+Yt(^iREeZmxaH3m@1JYOXz~w?`d|9=c-~dEW6dOVhL-b8o#JUYhD@ zu6s(JP_jBj z6$hv25YuPS>)t6^Q0ODo=gK2m?9wBuWb=qBqDK^-QP&<(HGUU7o3cB!x4+z>N=A36 z=kw_fCAdQ~It+w)>A3!I7}PW_S}?P&VPSn^%`DSlpzCO>Pn1pO#=R^IVrOI<#O$Xe z0oy?=fI)2izCkRM#z){o( z#~|RSZ|^v*G7tnBqheM>g(jk6AS!l36crI+ja+YwL{~(s=IwC;Zv(W)mpP2~IGMxZ zq3Kf;q7$gOcK8Y`EDv6R#Tu-Xm$JVxZzx$os&~)|f*WeaAwjBPL%vF0-|7t5H7c?(*RpKL)6zqAc&wNzzNOQpim z_9T9a54hO)J`fy6dSr^izl|6aFaH~;y2A+#bNXa7+}5Tg3{*&{i65b55OIeOzU#mpe!?nJ zkLvOGNmaalQuUE9sRg?d;nc5c?L@j$90*k*(!v1Y*-)DegZcfkk& zgE~GKoQ&^koj1|v=maK{@HKji;Ln1?5d~(qi_ycNTQalNiDG+lYxp||moo6+(D3E_emN1&#AF}DiW)FF$-sjl(zuVa z7Y&?;3Up@@vG6y15Nw7}ID8Oe+QwnTni?=hH$zd13h_%SLPib88A@RU4}w!SuT;R= zNSd~i@dlzZ6{y2O2Z4bO#6`hQYUUg~*6=0!mLXkUicdKP<${(~&33r0&3_WwNHuYnm@Tg!J9okIRh2Dk<}(w-6|z0Exup(Qwu!SLmO3-)OIxxl>ARA;NQ{`Iw7-KYtgACzXHwcdf!cqev8y01pgBZ@^ zwMZn^&Co7&gSH%K#~NtW1I#G4Wbip;tCUSX=k)u!s@P|4BvhxzH$@a5WUJ0%A&c=t5)Yy(EUxs z2bhRUdyb-QuC)x-reHBP<8vlfG9_px-ON%uN|a#QFht zFAVQXu_*_Z8#du!p8z)9z!1l#o1v50rW-Yc9XBI~|1envUZK3Jmwm?ubW&!$U2i*>Bq~==dBomWGKJ7IVZ9VNJQlDm$kJ&i0 z&ExU-^rRL{Xek5p!@P;`{V+AxBC6vQB4wQ(PQa>*-}@f9WsZV9NRQky$HON3B_N5T zh>k+7KO8kRz;;O?oI~IG0s4iE{t%+_!8J1*s_JJ{)mGP5)y%3Z5w_u|0z4Q+_2Du| z-$5aL3h)3EC-pQQZEyl?V|~p66An}`o`|)DBbqT$I}Xz*J|+4xhrjP3I!9mN=8 z1iMaRiE7U$_6J=^L>Cd!#YFTqBD#dl(@BA~kD2N^Y#kz^6cKe{9?NG4h=4)wU^`=N zddkU?ATvXYH5I__1;~y&Y#xwyQhBp|Cjt0bz zgqmX0M_=9@?W)56*tb!ci%e)&6`8+TJ7#Xw{%OqNyfG`aXfUxco(jjJyU?x;Xkoj? z#pnPY*W$5Y2V@u@+%&#bYOcktQsxt=pT1s8B*U>NCcNN%<5f)N4H!NL1IEM~C@_jB zeF0;8=lVpOAzsGNBu;tZC&w`5B}846a33VRMo^u_)Psa3x)2!tOnAr(Is@UTb$n;r ztrGRq6R|FMIj48Ew#TP)ClqS5npYm*tNG9f>?0szkTYexe_DBIYkRzsrgscM0TU$#`3OYD{pzJ_CF_l!gZpZ8jDl zN(Fc@(PqPkGDLvyQn1%mj{-Uq?yh2mR4*HM3l*9=l83xZ?Cnt%C^ej0SEkU^;^x{( zy*+A4pWhZZ{kBm0Efzt{#!eGgsK3>n-*}kn8C*Mh*5aug9ifSQD_Ouq2{l(~URr$br;kJ60_-h> zXSOYz=)fMtqyj$-V-NzVbb|9*g+)ijTbH zLvSs&JPawo=7&OD-u05Y@jWk3G*$X-;{t>~sQ?@JfU}|Q_}cn~Yff0XGS#?ni8goX@e3MHU7I>Ir8S@;d$5tHWqTz^R|# z97d0Iv&93;bmLu)2;cAWwH^=iIU{k;eoPr+8!i(f^e!;Ly^Wp4*i}rJQ7E{0aPi_& zfJ-4RMYv$7As;R(E+x2NXLz zdF}FJj$VAs@--_aS8u4UW_<;#YIrCHBd;>41rouIN@QKYw)wv0!$^*4yQmoFg68n*WAznBk(xds#|zx4+V_DKlRYmqVuZd2g`!Ug_bJ=CcE>{7V*0!o;B?mP*EBsp;K;NJI-&wg(a+jfo!E z`g+bfqJqDd-EXe_=^#YUTvAH(&GZo#^fb>Zft=$0Qlj!wqDiGh6{WiA3++C&l<1sN zqH{}$&MPH4zmycav(bVWN*)_zIBT99L@GUji=o(AtsWml<@7UL9>L{dT&xE3jFShWDx2rwqZMhw{u0j~4vsfh5Y7w$I* z@Js=26yR9`JX?Sd^QH&%Il}$J1^5U7K2m^>65zQ4JWqh<3-AH~UMRqe1bDFkHwo|( z0bVM=M+@*W0d5xH76D!^z$*lJr2rozz^ep!wE(XX;9~`NtpFb6^c>;XC0AC=$7Ygu2 z0(`Lme@%cd5#X;2@TFd&xlHnjE)&LqEdqSG0DnV(uMprX1^Al+e3bxSEx=m^_*(*e ztpINm;OhkV+X8&O0N)_MHwy4~1o$QazFC03E5O?Y_!a@aRe*03;M)cG4gtPXfbSCE zy9M|j0lrs&?-Str1^9ac{Cxp_K!ATBz&{k=2L<>c0sfHy|5$*3BEUZt;D-hH5dr?0 z06!|gj|uSO0{nykKPkXZ2{4>FNRx-pGXngq0RLQo|DOQ=LV$lMz|RTr^8);W0RKvW zUlib93-C(<{IUSQBEYW-@NWe8w*ve-0sg%J|3QFX6W~7z@aqEnCjtJm0RKgR|0=+L z6W})l`0oOY+!rAYnZK}iHA>;#O zAJ1bRqFXY|-L7~&jpy1wrSbgguO4iP zXP+1U>Y;CN_}72+(4`!H>8~C-kHdHT&BGQF@wxMF9y6TquD^Nc8vf4Re@p*%^cx=9 z%I}YP!$bFTcKi?~OE`{ohE_J>U%wUCG`in(&5)zRBT< zZ+O^(CqDi+Jai+!-|}v{oX5TEp>Of~9slxRdcr=B{U`m7`k{xm@%tqodg%Kc-tv)$ zZsqXhA9?5|4u9h#51aAebHzsS!(|&#WASt^J4-3J!8_e?j7T03(fdkJJw4#=&#eZv0faQ z%09EkrQe@D&P!MD`-hG5nmllVKmE?z2dClCWG{W2zpqVB*LTGs>34dkrD3Y{n*E|w zrt7<rdw(kf2(p{SRPkoF%%y%ga0e-ic5NgVztn*QyCSQt|ye7a8 zpPIh^x&U97NZ)^0fXkEV`zrMQB{kDs1~>(5BTi#Mg=hycI2IeowM%rw04tTcSG z07nJ*dI27McKZGC0(_zXZxLYi{Pg=rT$qOcBf!fqN#7rJX&U~!0Dt4M^nKsuY53;? z{GkBf{LS<`*Iku{KM~+RT${ds-1ap5r(4tTyU(WK3x1h~PkSK^zwu%k9{X|{9`;5W zzW?uOIQDiLzW3j0c>Mcm_-z4x|AX}X<`2{G`5&jp#tT07vfv(k-u^WGPC>8Nj3Kz` z&;nDZY(F9mKfWpr$2Jw1cwXF8V2-^{Pb)OX*k`5{n)>dL>4hfF3+JcdUr#SK={8oU z;hQI^rar2?P&LQ2stZ;64j(sWT&SAk;i#uobF3~OU1I8mH(n?)-?{UnGV}feAC;N+ zU;3!b)QNAtIhbze_}_bTuvz}Mdxp?e{Qg06MwtGq*e+Lz9$}7qA6z}cw6%V^ zHU0jR0{oN!zx?nBQ@8rR16!`S7S4BZlf;RyZ1^QY?GO-!HFx;hkoUTN@*KEC*mLHi zTYb!$RjU^+V6ICGBDSLa;NnFsA|g2IL_~P*3K25Fh=}0j6A|ILTST{sh~Of$AiB*Z zqGul!5y8JGBYO7HK8TLCG`5HUPDuj+0`i8|R9DSl|7xnMD{JfPfvw=^B@0&BH8&Pz z5Y&iJ2D9Jb+cZ$3-+aCT=FK-wK5;%{SH0gPlh$^0w z5WyuYA*y)99ilOBA1NV%KUYLF=Iv^ih(7+dgb2=H3DL)!`y#>;o>kf=DJ%fR>@|3j z1w`s3S1mosBV&ONTEOC)L{G|yuplKNdeSYT zr(_YqYL6q-F@0U}oLn`mqe+OKc3Yx9%80NCCn0*?Euwd2 zL|DO-5WVge(T6f3EdNP}cDh6~>uWM1tR0GoW_``2;y-GL-2GU16cHUYB<^m6JnElv z_hZ#kLiEq;-65Jc`fm~+VaZcOG;j1@T_S3e^%~YoB}8p58++b=Pm)T6#a0Q?e_d*k zMSj^h!b+`(Xp!Hgh%^nByC2KEBBG|jF1vr}88RZQ5sQeHp5d~MI=&?%!UD61sN)*9 zh@O%WVRc$UVPENx4O-f_v0>$b~?ur4klTDRRTqWk2kVNqQ|bf3#!iyS61 zB&IPUqR3$@+=)o!Hn~Jt&X*9~=C(xl%EJg^0VG8Cy6pb5UX)9OKmrlbSueUobiwGm zC80$Wf{5sX(Jp)Kg3&*a5Fvy?Ms$z6#=c}It z)vKg7LWGTk=+!G+mgqHE))1Z}A$rZFtlbfvER_hcJtCqzqAq8Ucl<_fBLoIXh<@Xe zv+wv+Muey$3DKu65#9Nyj0hn~BBDDVb&IH17FxtJNr-w~ntqR5C(rv43?(9ZETM*SbXXNK!(C=rIY=BQAUGsXx9eAwuYxgy@g|a95(|{wQl&#I1>lp8KOqP5b;@ zxv>%SCL(%%?$z!}^!$RDR5e7*Nr)CiTq0U2n|=tllMt=^u}efzAU!5(hBSZ;`h+duT()4?EiENA_#85)C#HBI%>btVn5Alf-qIYe^ z?70@#vFPYWP@{nWYX?QO;doV|i>(-}){-nUMW4k7tQc(D`Qcq6B1A+Qh_GUS=fI*a zi6&El_C$as@~}l!Re#?)5fuU|MO1k164m{49+OIicuWx$p1VY~ZRal}R0!u3QQ^5u zR1?eO!5`6}BC3gHW0{D!Xsd~3vO+>IsfUMoVae-=S_j0MN5Qi(G zTH3wLZ3Wv4f)Xl(@rtP03r=>6>df=x3L*+vM0MtQx-Hi-QH=@!+tolhSr4tX=}`SWu`R0tjyQQ^5uR1Y5iTd7otJr_~oxl2?N%jQXKh0t{o6`s39wR*_h z8^sDD@?AuQ=Ppq#nD_erA}R#Vi>UD2C8}*ZKb0zoxO)*5p1VY~>aIbri={%?zK9CX zU835yQ>_zGA?ja5h3BqOeIjXRY#NYJed1O-Z`=8p)K=JYAftNBZCgz&TP#%&TNXrA zchh376SczR^0 zq`a`dN<@X{E>UgU`3tFn*q$Y#!gH6XzEpM4$zlbuyGulc=Pprg+xekXDr^oDQQ^63 zRBuYCu(wP`^`?7NZ%L@IHBCnKmRnS7KX_i!IM~@HqQY~R6|}l@urW?VWw>)(%qFZZ zChV&dQ5h~K7pR^L%QG)*%M(#O8Q$r3Heq#pV^^Pu%5ZzTD3#Txk4=FhD#NGm0+n?I z4SNbjRK^OL3slx6RBTBUQ5j39E>Nxg;EAt^GKd|GA}Tz0$ye3@0c?mAQ5gXOE=pyM z5W#**5tR`k;sVvSoh(O}spzpCQ$&U5E-Scg=MG7nv71vywZpAAZ`-*;vfHs4)Pl;r z-A+=eu$NRuMea-Wx`YZ_QDs!G=YUG8Aa=4^P`R(*#|MfmijA-`s*ewJ-GiS>1|;^; z%BVhdZ$N%pA(jf;a4o1RT$gG`nTQIzcx6;O%G{%B6j5Olumx44dsKIesIZ6Fg6eLU zsAgRjzeGfZEyyA&Ja>s|+s=>Yh^VlGSww~B?on+PQDFnL1=VKPsCE>JsIY%pMzy2R zHL6b~X2AAq8P%umnc-8ZRM@?3LFK+wJCH=#97VDDTSm3Rdf=Te?>%vZTBK7Ja>s|+s;qCA}ak*;D$EYR6#LrP?8l?a0<(LFIOApLJP$i&!codk|6Kx$9DWEVUJK zMTn@j?flrTt?a_puhLe3TPzh)O^B%Q9HlB=-5pLD=g&B8c|(2*0|Az;%i^ucs#JHl zvmJ>P`=G+fCf3bUNLnhE32812lvu#Va~)B7t76fy3sxOh$b{LHZPGv;S4x=JL=F-lJa(L3>5}!V;S8pcT9TR^N`?d`K%{X*Do3P;PRMu` zJK#a`6X1D#`IlMe`ZmV8BDNKzWe#YNHw9=8U#+7lTh|p2#}lzoz_tTe%GOMcj=U?t zRo$xND(>896BFW8DP(H_hT%b8sdg_~*0e1Wxf&U6fb$2bb!_OubCha$cQ_h~btk*xp+HJY zB8MxgIa2?-sxur+#FDYL6dL0j7CIt+WX&<~W3=7ByQ{JlN&2f&i9lOhIM^A82HLd* zTBFK=a8)oB2}P=;Qh|0=NQ;EmYl)3=kuG&85|a0zNIy*J%{VC&1Kt9Uvnr0G8dr~KYKuLl!|sOR)tZZDio^>BR?#yn_r%Mwy^i@!Ww$4hkd^fsGB-^-{U5gs-s>76~FvlR*&7 zI(^;x#_AeJbX8iYU0bJZ%*MZyvZHe1StN}TOEy-ksjZtavno^-SQqFFgi(rYMX1VN z1hF<-9U2OGt5BRnp3=FcCKOJ_BY};_BouNKWkFw(Isw|>DQAXAW&HWAq zLlP~qV6zkP%3v&-?CR7KNCg|Jl#y4qYq8EiuH0R1L6Wt)r#loGxxU0Ak4r|9ru2)$ ztkb|VJ{d^{(}RZivx^*PBe$4Hdun^6wF>lg$qxondC30QOcih%1(DedB{`IH)Py!| zhA_5UMh~Z^nAoPx2qrTB)=A8eQ%x)dYmZ>}uC>Pjj#Y6Ql#$j=Do&eLEA(=Hs$sm0 zL}ZmK9asfv<;1eohGN~(NGuR?t&^QPZG2{I-*hMx^4p1pf_2fBhjmetnY_SAVpCn{ zP%32F6H7HVm2A^;RG?GD-y}N%@o==A$)Z&hZgeOJ()^(y)3{L0W@;jotPIYqsj03^ zSExM_YYjxI*ujF`I2R>U84M+>f~Vr_L}q3==-r94ssdeAnOo3K)z@A3mor4oizI|7 zX-{p0sd_wjAgQbR#+q73-TW#YujMs7|NdgRyi7CkJP3M8u9szMQgv#mPT zerDyw^9OY%*$Cr|_$G&fB5^1RI*J#xJQ#{&M2~dkF{;nbzn1qplo1I{QN}U6j7Ksu ztyQT=SARF?RNkQ3k>li3aXuvqFtVr< zH|v>}3;yj61xNl|6#PfL;QMJc4Gnb-RiR|CovRNwv&H$jlqW-d?X=63h0A^-GAB~} zqPR0Abu!J5=UKH&L#^|y{2Yh&K^|ccoHI%1vi)1z1=j>7gKdFiDw1_ZKXHb$*@IKZ zMTul*cZoGe5@Qr(@>EuHm4#|$@Vl{-vMtzrQx+aAg+U_|G7w&Qj?t7yvoPokIJv*1 zW`?7p{)wd;VhxaP83h0LxZadUv9Tf9HV{K$ojw$58&a?UV$q}C=TRme2WZLimWitsI^uEciNwOP=WlJx5 zPht{P=evp~aAj9)-D&7pA&hi>=oZj^nyyt~f|5 z76P*2y3C<$NR5xOJ;2L0R;#I=F|#@+&-HW{Wf1FQXLr>7 zX*73`1znH5hvrZVJDIM#_A9H!Zo!!xDAC(*>D_|oS-YjNrqQum>$44qtLI9mn;XEmM5xa26es~H(u*Qvu? zuar2M#y9{61wMiocw#E4dvdjCD94qXBX_Z`_8ofkM`DNKj2;ws!?_9Gp+|p|y+dmn z@)&QHN&_7Z1OnkFZZQZi%|6gI)HsJ^Y;qWHaOw~Up7@6Z+M^X!+cAdfoQze;2zP2V{ZpB`dr1F5kZW z?^y}gXK~}%jVg89Uz6hOaT*s0KN2wrzsBP19sP&(S*#eRcq<(F1%k_8>0-P#eck$o z{)@NDhRP`r1P73zWXJK6A>L|6ePd3u)~eiU<1}x=8E7a@D=$vt0IW6nv*C1#G{C`Z zDBwC?K*RBs-x|}*Y(>dnCTwvS*Kk}MO4w!eXrQLC9;+fbEUQ;%E0=XHY%g^;eIklG z&aOkjPAp%~#r>vFvWt6l?z+5e>4nn9C>)dr!goEY6UOtbgtG~ileptFJ`nuDqw5WE zukSx`&xXoru@7ehqGXHS*GpC}_z(JJS^uzIaCF!+(e-zVOoRgsQGw&%>*h>!{he9+ zvcB5csboiZ%A)2gM8Y^d5rn(;-@pjtd3M5iSfX{?pZ=;y7)LdN@TG_7gz-E(;VhmI zyBgPR-+q`#80SKQ@Gp-v2yZ{k1>xN7f+-7^-60ajA(SBeW}G+m!ew`4CEQT!9EY>Y zGGrnS`{RH)#yDz8SEPLCJ^B`j)g$7H4vT+z~hGCC78A+ZehA(1dnMFruPUeF2Sc~-*pS(x08@RUW%_7e%? z2v!iT{nTvg{jw9zGPAWKT(|vt$vK1bUP1VVlQtSdcXsDYeYLZ5#*T2)HN{b}#yDIS zgzxRt3FCRz8aLKB`;zSlmo5FePb7?!Y(ZH0o=zCgvl4E|i>oh^yrnoc7lemBY7oB2 zg|{@1rmow*UCPpgGkQTdG5R##$J<$!CTBU$VjI~t^^}FnUXhxb6F%!eoiLtfZ|Yj- zrFlETWlJx8S|p6qhf(AET6DsAo}F+WR&CQY#gda1M;(LkqhHbq<9SxX`MBbnt|^X- zHO9HhApEOSOu}&&gmX8+%9dUzaN)goh0M3X@|z z&tBs^+<;Bj6l)@39K4MhPn=*9*0K}MuaAQwVVv>}!qcajgo7>!=RP}ax~5p#Q;#FX zLHM!5O~PzXy(3pQW(g|Fz+6(6IGkS&!l`*CVU{H>3*p>tuBK~>+r_5FVd)_JRGUe- zJ$qB6aIMl z>Bh*#4n}b1>O5?&x_{hoj9B9bIpJmB)CuEx)*9F6C&v+y@T#xqH7+^w45P-8tb`l$ zGU#tOQ6&8M={n)qk9ERz+iy5AE8+V5)MA@Rxc&^C@H4NQHEzpFxG@hWP}4QVog(4I zn{>jPW`5OZYBmAR!d!VNiBm+v5l;9oi%r6(WUp}^OC?QPD!N3%Z*JyI{U#^8rGg!N z;#lK+?CPd16_Om6o~aZ5%||BT>~h?Y&&aiH<1H20#VK2Gx$Vfc zr9v7qPv(RNRhWdc51H9QTrvLq6ygtNPwvW1RhsIlbB{0}F5PSIHgVHdv4+B^*Ut%c`{T)q4f zy~fuZbhb`-YvK7>xw<|No2zMSp~PIHF4YM?xZgPj;q1(nmrHR=g*03IJ12bC1)T7f zitMw+hJ5BuTMG{toBA7<={5Ejoom$i@a#>UAK|k_!Z;=j2K`$h-cd}+wXyxm%Ok=V!AU8NJg?S4*pYvDyM`Z#w-dDGTHDVgIZoN(dU7Z`oa zk~uo}aUK)%rmck+i#7hkwR(*|n0BE-_+l3|&V7xuX-ma=k??Wbb;8SD=Y+RZtj|g~ zTcoNjb6ry`8GC=aRVRGou@~tzzNR?4vDcW#x>M7Z3d!s9?z1}K8*aPA;OgvNpFF*{ zA+f11_@z$xoIAd5)Hsy2sT=cHKyTVwc&14Bv=?;3&s=+{!CYr%C0w76FLP_*c_QIA zUepOc)q9yi_`K|d^O-GfEj&UbJoaVY)X#1)2p^H1a6TS^t%VnggonMM6MprK%MHR8 zW+$A_#C%JIgZVw|qk z)kYs@A3(CD=d&HFw^Ss>rhfkey~dw-w;F_#S(`drAdD^Ht%VnegquIq2|xB%PIznK z1z8DaixF_z>2&_bI>Fl5wJcm_O1vu(>aUC4VgE{(&I@#TDnfR_t+Ng8=c#%VP* z)wMOVsscIWlsG6O>1@H-O-)u9ajUBn-Y#C*77_7F`9}z`OTMMOQ z7z%oI!c`YuXAow`Fk~QXo4289YoT;x$W4b9usOu{%fDmbWJiW%z{$6w=Cj7OwNN^} zVfzs};kMguG6=KN8?q42!?4{_A$h7FU!@aX`suAY;Vl)}J=NK^F*>ntY?DrK)<-{K zf>h43n}hZrxh}u>pJq6 ztU+dG*(8%8;@W9rRV9c&@0EE}X9u{%iNI3>iMxg-&u_%Cs8^U;3VW zqW!O@7c&mJ`k_BF!Y_SKKTuhUdMr6U5DjS?7KD@Q>~OCA-~VdG$~0E%IBOr)apE~D zlL@EOR?wR#sjPfI{lR;T!!3DWTZ3((%JnlV18uo(@XMB;)@h$a<%N2oZolvYR;XG- zBUWl%iCA3QwQcW{4QyG=gYQ@ro!A9cyo7i05>Ab3m4VY(;~Cg1J9AB#TVwvzZ8e?t z5zOF4e2o{eGN)8k4#IIDwg+cJ=Ctp1)YE$R9(?crSoi8Ffm|d4$UWDdks2;La;NS6 z<)cfOkW72x6IS5Sftp#fSgtU)d4=kQd+(<$*DlHx)w>3*+!8nGikEbx^^np1QUsE=4YqY zdVrTH@Eg5M(}VGB&ej}SD;p}O>|ihPk{$S(UNW8?%tZ#O+@--LJ6Lu)w>u1jZ@xL0 zb@jP_o5;F)j*;5Tk;ii{_`y8GW70WirjxDo9xv+Uyr@DVv;6XA>e)fFlqf@8uX1S9 zw|j=LHm!eXGHcUAQ=OIZa9c>GKYnGlCWG>Vs#6aohl&Ls^(xP`oW`=G$cT!;8|n*t5T+Bl?BbZXjak zVw;G3&Ea*4Sj(FEcDrw^hYOv1wT|t^?O$iujKhUYY-Q!;`DJJZCj)mE%|Ulr|zpKjHQck$%Q87@3WtBHpd*&@P6 zMD!#_bl?;n5k4*v6-XzKJ;f0-tcw-mgEg9U}RJmy;-@hu$HD7@u0-|~uY;S4|h zEe|NB-zpH_0y_$C6_~gR|37>00w>2&-3#~XVM{Xd0~_-QnA+9^?b*ckzlDsR~25D{g&eZI-ccy#X-LtDjmah#Y5N=3-8z2xq-jEP3A>m7m!3hBp@&NJy z0YV;-2XOIC!o2}PLP&^xfB#d@?&(>r1R?&u-`BQgX1l6RojP^u)TvXaPT9F|(#y)V zQRlj-SG19^NBAevsEfDY7v-`u;F@`nVUx)K3N9}X70-heo{A!V#2Y-02T`^awHv%3 zyY-Ol4s_-9@;5l}3i=o(3 zvAO3`$8l&&-8kRoaWWz@J62|5z;!zFrWTJEy=a7vWNcjWYGI5)XK;!ayoh7aVf0K(MDUHP z;(qfI=VgxbD1C0Vkow>yj`N{QL|uf~)*7#S?MA`~+#{Dby;}zB4KH38Y_-XUYkjLd zhl(Q}hm9p34SF?P>a^C;zC|)r)oWGj^C*Q!(GA}qMbE?Nw)-8&IqNvi`iGrg>T$L> zQ$y^D$7zKAjR4-uU6~xiW6><@WBbU%HOYW9J=WYthb3dn|pegv-zpS2kY_Y zM&@j~{8Eg($9tU(%<0{-yS!thvSWB;SoCzvt3&g+hwvii^Z*I~T&~Lw^f&}}-Dc)& z-UzsYWx9YGIn*&cYpNqaqCtr^z6YHtLi^%JNqCCU<~-_b-bBcPBA1+wi~GIAJLV+| z7{MvxR2RJ9X339lwn(FXV?;hE-$R;Xc;kUISMMRsRsOry zJT8A@1gps%Blw_vj}ffI`-^&nFuY2NvZphr=aS2za9!?f-mvaQrFA_O?+CXImpgK@ zBQB;+oWRJ>gRovhSl0~#vEg_QfOSBjM*|Ryo2i|KIPPb(Ylk>?&F-}L?>P?j_(SsdnT?L~uj{6Up6xvTmL8|q zX@>0}X@!1}u#-u%RgY&`;w|!k&8;x{`vs2U{JP^fzu`E}kmER54*WE!Zcb0taUAGj zm}y?`I6ZH09OoAt$9bdU^nl$y;XpWvSrSUl3mwNfCYJ-yA7AV^&amTb+JA+Ed71RS z>k*H_k($|rOg!W`n||{tjx#9}-|9G;{NnH4vl7whJFS@iBsr?fAGBAN~0FajTtAcbwkIQfaWp z=_ZiDR>Mo`VbsLZcW~6JkB*khrFJ|wIO>)0lxoY>;la}jRlm4Ut(D3pubqU0zOAh8gRM6ow0ZiXA1Y68zUUfo;E$A> z9nH!Pcv$gscUJ!8U;bs1KL1gyd`(wYCJDACUcRO)FB6OlU}gtA=z#w=5(r{INJ=b= zyjm^daa_boZD&L3>+(J91L`*{EO*QIm}Bme zzt609oJPi+3ww&~LbACB&hNW6e7Js*gO;Qp%>A3@yxQGc*CC#B)WL9@w3pO#+Hs?0r`>#! zT?f{l_R~?v)w&(9dwNlgg+XJ5<<-LMT43zbe8qaUKC;$Y!YXY6cnBq*jo<|CeYRZ- zEM`_MW`4%g(U!|}TaHfeyLoc|T{)z(57uwqY=ghyak~jQ;4jtScg}?Y2aiM}gHhN{ z{9s;v7ZY!;LFOWi^L_~u-~G1^RL*4?4Q0j3uJA*yWCTHP$)0G}))4)5{ zIYapSFB^UnmTxj9+~+u(zPZ@r%wvur10>ksX?KVV-q{Jd;hn|R$ZsXZ9;f%xJ5Ch6 zTCJFbH1E_Mr}yeRP84N^s2vnli(e!V=_&O%n;si>1TL2@E&!JY$2Jo#kG<;E2AB2u zxLk3QS6ytk*a2MR&hFrR5qMlC-cAHHfg%u*?=Nz_7WTv|FgXe=uH&6W){^!lHJ-s#NZ7DtEUk zw+DFTC*2(ecT13;w-DWMnJn znC-)5u?HJo#My0aueKYlxlXobP;d`BL+ug$S+q;(K}d^Z`yiPva|4%ovA zB4_$7c;#wfNl;R0*ix8_{MtM(^3zF;FG(p%<`0?Bj1ynI#^!)|UBqQakzeB~8B?T8 zUTSzjtlmSQ&m}xg)C)-RxnzMhQPn%F_hsQ$7$wypiInzE77;6rpVpAD*CJEuHEc=I zW4&#fx2UzsqhzpZAU{*Ri>thKch$Q)iM$~8#O*o?9LPikW1c|4pnYFFm~GVebImMH z%L+_}>oz*r$beuqFi=sLv}92tngEW3$W!k@5Az<^d2&rFOuE&DdKjeWP;EvKF4g+H zf`Lt}YS?UgK@D6Ugo*AeESq#vi&q=rydS7?pkHmF+8Xp4JkoWbd+BYp;qxF-8UgLJ zTkr12~TT8KVH^w2BLj`c-xN_ZUz>vOW~z0`3!W2~Z=>i&Gw3kIuUpjp9s-QtD=(Eyp7oIq6zt@pIlQ}4n4 zGJnLI79WD%GC_P5v6ZfhiP{^y*z_>rsMn&F1~0~8JF0Ts8=(5U7q_CY?i(PeVm|U( z3s@UqNj=!~46lP9(y4RdX#)~&Bbq0Y{>qLf{r#UXCc)I?a3~2-)Ytl_ZUoM16+zJx`Otlr_MkSCu@s&M=lBnV$ z_D|>AUZj&CiTwFys}+T(R|e;Kz#~ud4M3Vif}m;x8YZb(S2i75Gx)7m7&i2%hONeL z#k@MW$hD}!n!}IoQ}9sLqF<|qK@x?H)Z7GqYw((u|EdVsvw^#ogKD(WA_oCHXEDy@ z_t}k8L$Tw$rN_C^sSH=@RlaN2=#Fw_=jiU;-iTK&50!_#-Mn5ME!Qifd~U9`Yh+}! zysNT{*Q%9~k>Qci^6ugC=h96eox4Xzz4GW>wNfAT>N|JM z?c6oDqqcK*xnB1j=koXckC)Qizu-9KU)oT9(S~=d>v7h-sHewyd*vry`L*d+y?N@l zK2}&?+f_KS=f6Mgt9zUi&v?;o*FHS?whuhzx8MH$_Z*ym`+!xFlPBFZo9KZ>}2ry`TQzQ=T^W*wI_|edO?0N9m7y!Mr^d&aXq zzwx&}@`d65_Jwc!;jjO~kC(oE$A+iAaPaoOe(0NV-}ArR^AF#@<Bsy2<&m?0wX6BvPrmx1-e3E> zTW)>ynaj8R>N|V?;H~Ya-}T+sj$BuI$HRBM;rOPj{^@`I>8C62{@Y)D*?rF(T(`c* z=^;wI^qZ$&z4GQGrFYK!_ji1*H2;y;-utFsdE=i?4!r*Cci!|@AN=kW8>Zg$|NQf8 zxcr%yKYI2zS|=WQ|BG*BfB5=qzxIWPZ}`+-ee|BkE_u(7?K}JMO+D9N_R6RAU%ve# zXM)>GZ~AEC7r#`vc=@r>m3^;aAAR}gqpx}59o66Zo!ymJ?EA0V{^-T020z1I_4?;N z{-SRr-seB`y-$Cvc^vcXz9%#Ui#?Iow)3_$G-K; zFI;!SB_Ds)+YbKZE1&Z(&wcQ#&-~Z#?LYPJ4}Wy<{ReJ3`jl^O{MHSB8b5N|mAfAM zmoI&1!!M5hU)Nvv!r9^1|K*$SJNlFttb58Y{(bnapTGRwU+lZ%YwvpC;XAH6+4|&P zf8f^d?Y-{pFDxX^CC`8DkH7iE)&s!d55BSSeclVAf4uDQ2iE`2ROw%jJ+%3wN0z?8 z|KZb*e6;%QpLx$ez56GA>Z135F6o{5*6)|xzkk}~w@RZgXFs?1--F8@x#`N!eE-q! zAG-OGnM05L-Fv=wEBm#pUhK90@#5VlKd}42Tdw=W){BStOeZgW@4H_6fscLY^mG2^ zsz2ZShY#NS)T@5uwa<9!Tg&e6z3$&X`_*+1J^1whd*?eAp8nMD{^GB1>3!_*eLu17 zAKUFe-WA>T#dnqO_;T&FfAF2Ze))6PU-Z}utLuOFhHD=D*U!J=`~PF=bD#d^6&wEO zT@OF+eZi4e&pzsH{nlsy=qF!&<5wRo^*r$MXZHW@*FWHY)p^OMe*cnzuYP~}hFAUD z+a5mpv(LHWPriNEy^nnGkNbPR^MZ*FhR^-dxdG+pf4?Wm(=1U*`$`=L(wx9a= zd&gVO{h#@r>hPrpZmC~8GgiNH?5i*MvyZ;v!(Y1Xk3RmrKiu?zwn{` zU+%l+ir+i?mC@O+y|a3GwdY^H@SJCTQi=}UjARRZ|Heu?Sb20@+XaVt$*`h?EICVJp7KY{oCCWpBUKidzaq%{B_r3 znbAw;1eyt&UbST@keCUYJYIlWrsX)SOo5lQnk_xALzPh53PzQsjM!|5Qu;eyRg-22 z)7Ejh^{`FM0c7QZXCNNTIO;vN9-bxNW4;)czcJsc_oz;l{U<6*cFULb(6qftdfmZt z)zgDb(R$J<=qv{u*!zTI9vQcgWdmGgx9L2WJd5%Orz<$K5EwtIKFgUJl7(rNy@3iZ z3=a(t%fjoN-@VdtK7J*&sz+4>Qy_f30Bj=xi~W`bj4-)~fVEmSw%4vpV{$R&iITX5 zc^(Ajb4ju4HMm|OsRY>KQVCc(p+v)5;nA*E6egkWYE_7ooFw8}oxt>uLQAI`UNE?n z@RlwEo(XtDCeb1E@1)~6Z<76Wi$m65df*XvuY7;laj-o{&y?Kd$8*GSoR^E&&QU18 z^7m)g1LoAwxC1vvcvD`c404kkzkUpC{VaSu6CYa~r+M%MLYe9@1>cLtN7w>EHXk~x}VdB^E?KSzhu}>9i z;R2gHwzPv)KBuvRQ?kZz$Z&-*ZR zDTB^*7$$7r#JSP7$>caaL^>iOk@H^NB;6cv?yb5R*MdT(87U$i3d8vZFT&gj0$DZT z$<*|&{F)A*qiZ*j!~WyF_0`FV{+uUt>@L;RJ9K)c{9DdVh5Jxn2?N>YZQ|(^CfHTW!Q|*U zFgf{=-y-MJ=dHpQL0l=d1D=$YW0;(Rq*YwxD_WXBsJB{PbV~cg7BdwG2eE zG>9lHusVxI2Ai!$JQ&4Gt-+R;Uff#yZeiT24|1`+UJ=5cXMvH~`01qBkrihy zIE}? z`a47Fmfwt<1W9GcK#>{h)nd|Y>1BH^l({(4YxE371eB`Ls&dm~la7&KwWS)ibSJ_f zVkOnRAn{_I3O0{M2Irft;=Q4<0zoaX3K_#ihVIG&tf-N}W0f9@{8oyNnLelF3>7nV zBa7EIqb~|W_Pquy(!;jq zAX}tR%{KpK6H`{iY$7#Rb%pGAU2odX2osKyW48IvE=BS!g$*=GRf2=sm3g(L+F&cA|I{Zy5Y#)<<2R5U=9BTr!aM5u#-G9sCLc?)3eJ5UApoIoD zfbZ(u3d3eqW>cLz4*T0p+vJWHOF}q7u>_JfVat4u9E)Nm)G*~B#bf3NA}hSY7`(!^ zZrR3;^Elx(w(KVhjI88|zsPo$cAQ4y%nGluTf7A?c%kRdu|ei}Rk)DcxDY0E?^-o% zBHv*@PDoGQx@C;`lO3L%Ieuhf>Hu?>g{wfDJOyG@>!QdV5>F}?v*iW9y1z3~AgZz??oZ|%p2g1U%6+VXWR~T1~*t2!ZS;iYN?`-=q z*$qN6!RbVkOgFt5E}^ycFj|IdAqYTSjF*0$#HZ@Isu!fhlAnMC?$#}5i2&QAhXN$7 zDnj7GMuS%q)`aUAz+%}IZ{0Fh4lVcVS1XAwhmyi#t)sh;rb)DbHfo?av3UTuYjDL?JUNjw0= z0(SJ)0Tw0;JX-c+&iwfxj5w>cTMhUm`C)K=15@*_XhM2q5`_-(q`E*%LVQ4M2?|M; z(KLWxa4m?DsS6>HG|TqLCLfD%w1%?#0Xuy35EB!f6bOD$4_Tip=2X#SC+8=3-u8 zo6VD_jHNT3Q-Mln@1{Yeb9Ggr(%JHLsC1ruB`Td~?OIf(+&R>!Ozt)4QJE5JR-`iJ z{(nvCKT4C*^4};xKRQL~Nuf$Xpb1~k{|rrPO{z|MP9;BSJ*QT?PpfFzf4+h=)(Gd7 zI#3z2=6weBT+#l?raPrcK9s@xNvB!)-MN5peex+++kw)}VVnq?kx)*PkU`IoIv%NO zuXU7t>uRN8WllTTYSu4Tg_?Ee%Y~Y?nNB$5t6AAo6CA#r&?n6jppFw3Pz5ie(-kBk z=!C_gEefk=E39&lJlMD`Kk#`{{VoAc4m`#_Vh*^#;`X#$5KsX>yLlVCBl43(oL@h- z;5Qn6i_Iia*qq}L#upnZS9W7O?f2s(^5@zxu(g94k4S5tnmo=Lew7C?M<(?zS@2_N zMu?ebPIy$kMuXQ_fevsWvtC(AZ)Mi-1I|{$wlSa0H8?u(-ZpF)Sh~5QIE%w39}M{N zU_ETqctn;sTKP8`gqwIBvt+?bSipG=VCJ|sZ%6|j(D3V43BAao1s1Oj&^j-ci>eyL zixEC99c96K_>@FT9ZM05>aAOpPro?qB8(f1F}95rDlFo4E>wRkp8TNIPS}zc`J&Ye zoFPyXYk6@jY=}w7+E^Vj#-t7!@a2QlepY}HL8NVC%Y1vIfzqNc49t*49J`T>M^PBD zCXZpakyL7WE6j_0bf#4W<(!J=E%1_H0=ss?JQgFy5{~eQRbY*Uf~EmqmOVj(ae%>c zzr>lJC{+CtFEN*T6UPV!T{g$7VUx$!OBiR+=H&&y!C7D5$+4DSU1SB*`o5E64IWr; zW?7L{`e*xLRT|W0B|yP57IQF#qFpDva#x4~m9vJ{-H72OM2tB;?+0YYI!}@eYMQKp zBsndhW%~s*y}~+ZnQb&#`A%Z@hZ`f$xap2r)@vK{B+&)c6+1C^yD6|eJ?i3;iv_%V zXt>q*Tzj6mG>pbrK|x97i+IwGY$lLEtj+>^l6gUP2CO%X+L44(G)P_(#($(!vZ(oP z{CziGl#BG#0W6#*&ppH>7RvwHO!gixp48o*HA}L+7#IxRRG>-FT3z4i?pCK$Of&E#D6;w-L z8c|4-p!Tt40fPu=Bc!IFgdYZM0SB%FDRZ{5d%U=~oGo@1LEDM7o^`!-n{_X-#kqzYqY&?TW7&cg)j8e5Y zDZ-Co+%4EdaT)xk+=8UE%WCb2Ok?BaQn_4-nQEEh8I9TanH2wkT%Mm8n->Tx41hS! zn1n1|2$xyA#bPooMV$F@upL4&@~WIEid4g(<`azt^)c&Vf|N4_rZO_^B@uB_Eu->DhuM`nOo5Xf2P0uMX?u;vikj&}4#_7~1h8Rc*+?Z&JBG4rILOVI|J0y_p}!!& z?Hy+$Wo5Zn8SrdlUOnLv8!5AES-Dh+g{3pboVq<`bDRfkgvA`RhzI1(nc#O!)r~Ni zXFLeo^9!c0@sRjdB7nI^%p_CASRwnUHPw5GH8I!{gJ5ALAy}?cx@4*q*|hL6sW6_) zXH1xM(OO%EVZssAQdGN+Rme=qm=RF9B8=ECt8?(0RyCCF;cndmtHIeJ^%J9A3L~D>wUG49o(ltnJnZhxL4-Df;M^c=55vq)va4-Ob&`M*$iu3_$<;W zRNjkK5B`5~spil7_yrr>pz;P3r!L_OxNo9VjgnG}H}`DaGKh@wtnHwWk%v8{1}{RY zYgfX&!lXyF79ua^<1V;BU?|1Lg`;?A==kB8>6wX{n_k(Z zjXe=H_H5m^DA6Nk6>fLJ#>7g2u3MRSHLCc+ik0`UthrnjTw^IP)w5wDu(8^ z)tOD_?P$d|8tw{|jo^+aJA!vUNf7kmycTdcc4UY-IWv7oboZT4((bk}9D0(FGeg6f z#Ea@aZ`1@K!KqTF7AM-tLI|Jo;-M!A@)(GI3qHSa(PLht5iS>n2Ut-l)Z;5WCZFi0 zcN%g1s_iJ^K|&7jK99#M<+4r|J8sAoaB&!Xe5j1YEd1eRs-C0PUZ9w>3owT7e}`C~v#_w0)sl&SDirQ-=d zy^5{Zec+w1AbsxH$~c$_fCKyB#j+f9xEF2^)22EQgTQNsl~#AqUxgcOcYS?sLFswt zed>c%T(%I#i5d)Alk1B0f8r4pHl&fIp>b|xtrIEfa|ocEefH-Z=R$JnduS+gghQSY zF$aMpx?t1M(&&>NT}53vs(#4m=AJiMoq-PxX9z4#rgYGEcZvRc@*}J$T-mX^RH+Q9 ze`G{jRakVK7P5}cNG97|DOGk4l`5mVOG6~}=tRBnJI;tTI)O5yPuCLN0{8DB4e9ekaNO?aWzPn@Un= z6Wv(owC>m$cag8SW3Ic0xn#4Y-)Hy8;!sce3aR47y{<(aw?B_ta@d@>I76T=;3XU8 zgYM)KF^I^ZHa?O|D$9D;=N`bGmfH^=*v3wdC7~BZ-U>4`85cBx`A5+Nzt6I>)CjAL z>*7rp8WRP#Zt2p-8ecNaJmcaTiGVjyV@yFS-93b$5iEV#PB6uD`}|MF^*zVCZb7z?k3^t~uw`fgGH zAbyi8w@D#-bcTr#Zo@r7q(U++=0gWs{L%JTplS7m4|jRihIOF;G-KU z{81@t?-dS&D2wHwAMse%Gk~R8?1#blu9Dcv)>%a8>>><*1HuT1$zj_zxHXVr-fJk) z6pu+CMFeh>M|bc_?1M4ddOXRLP!JggtyLb`CS?FOGFi>Ss9t8uX1-0C=LJ0|%SkqN zZ#YMLRf0K{I1si?V;d8jMlkP1VO&x~86X+2QuMuz@rp;VtN|yJ1KTnq*akz z%4vNoZ3S577IEAL60RCGSYM$7xsnQ8M~x~mw-m)yx1WXWq}5KwX$x6NMK)X9>%udd z{CBsVMUR5wi2W#B1$fl-1Fr$vcWs*DCD|?!!;iLO5Krp-8>OwMDe|gXs5xtCO%BSm zLKIk?WMfHKjT&`!Qn-j)oFKBWSvG6a(ugN3YldmG1e>N^_u~tGEHbmY*N6eaXhR)6 zm)~x%)z&Sv_a>#Ish;*b=N|wn z+7SYI4*CslaulC`KpEdMxq^8f(FP@Rd1XhvUiE4tbLH~T$gbf^xxBOLc{_%^%234{ z8mf)*-Mh-=`i}bC?rME>WT;*q@^+O+J#VBovUBH7L5>vs85u|r62acAP{&K5VbPFg zVjsP?udk0x$*N#+uRGWF8;Ktjlc*ghMK7o>gb`-Vapux1UUS*~_p?)G+ljGr0HN?< zZaFHQef3F!^3q?pKnLcIcp? zxs$Zl10~7=4=)=r5RAIl=bj2qbqbB(>_I^RG7|U)FC}!(7JI>S?^ve1@*3Aib@?DS!q!40J3+kh$`5C&8N9F^VAKqE0~7+LG0dfR#&w^o!?cQWMf9ned8>%AK;x^10K>Cg66q`)66It>XlG_`$YwE9+6bJq z&#zH(79&>;ZFMk83S2)JKf^jQ@3CGX@T|+uT0UZu@kJb1P)*JXnnWy%we+s)L{pZO z$aR#<>IG??;DYr5n5%LJlR`�b9cqDj1Ap{tt)uA!s_tty$C(Gq~OdE+3ZUvid;H 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

  • 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260302/20260302164004-Binary.backup b/MikroMaster/20260302/20260302164004-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..94b34ddf073bc17cb12ea2485559188ea9340cac GIT binary patch literal 289184 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 z

  • 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%0A78B!UiRs2D&Z|v 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260220/20260220111036-Binary.backup b/MikroMaster/20260220/20260220111036-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..fa7f9ffa4ecf9fbe9aa7d095e47704f695608e95 GIT binary patch literal 288926 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 z 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260220/20260220142012-Binary.backup b/MikroMaster/20260220/20260220142012-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..7303ca6b893685cd94e045bd6ad3b1ea6a17d0ca GIT binary patch literal 288926 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 z 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260220/20260220190012-Binary.backup b/MikroMaster/20260220/20260220190012-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..29826fe968471c4b77df19b698ff0620a6a406c0 GIT binary patch literal 288926 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n \r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$SourceNew = \$ScriptVal->\"source\" || \$SourceCRLF = \$Scr\ + iptVal->\"source\") do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") . \ + \"' sources did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;}; \r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/20260220/20260220210012-Binary.backup b/MikroMaster/20260220/20260220210012-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ac4a00d4de6c9f1e151ca056a0639208f06f5f53 GIT binary patch literal 288912 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